123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #ifndef CERES_INTERNAL_PARALLEL_FOR_H_
- #define CERES_INTERNAL_PARALLEL_FOR_H_
- #include <mutex>
- #include <vector>
- #include "ceres/context_impl.h"
- #include "ceres/internal/eigen.h"
- #include "ceres/internal/export.h"
- #include "ceres/parallel_invoke.h"
- #include "ceres/partition_range_for_parallel_for.h"
- #include "glog/logging.h"
- namespace ceres::internal {
- inline decltype(auto) MakeConditionalLock(const int num_threads,
- std::mutex& m) {
- return (num_threads == 1) ? std::unique_lock<std::mutex>{}
- : std::unique_lock<std::mutex>{m};
- }
- template <typename F>
- void ParallelFor(ContextImpl* context,
- int start,
- int end,
- int num_threads,
- F&& function,
- int min_block_size = 1) {
- CHECK_GT(num_threads, 0);
- if (start >= end) {
- return;
- }
- if (num_threads == 1 || end - start < min_block_size * 2) {
- InvokeOnSegment(0, std::make_tuple(start, end), std::forward<F>(function));
- return;
- }
- CHECK(context != nullptr);
- ParallelInvoke(context,
- start,
- end,
- num_threads,
- std::forward<F>(function),
- min_block_size);
- }
- template <typename F>
- void ParallelFor(ContextImpl* context,
- int start,
- int end,
- int num_threads,
- F&& function,
- const std::vector<int>& partitions) {
- CHECK_GT(num_threads, 0);
- if (start >= end) {
- return;
- }
- CHECK_EQ(partitions.front(), start);
- CHECK_EQ(partitions.back(), end);
- if (num_threads == 1 || end - start <= num_threads) {
- ParallelFor(context, start, end, num_threads, std::forward<F>(function));
- return;
- }
- CHECK_GT(partitions.size(), 1);
- const int num_partitions = partitions.size() - 1;
- ParallelFor(context,
- 0,
- num_partitions,
- num_threads,
- [&function, &partitions](int thread_id,
- std::tuple<int, int> partition_ids) {
-
- const auto [partition_start, partition_end] = partition_ids;
-
-
-
- const int range_start = partitions[partition_start];
- const int range_end = partitions[partition_end];
-
- const auto range = std::make_tuple(range_start, range_end);
- InvokeOnSegment(thread_id, range, function);
- });
- }
- template <typename F, typename CumulativeCostData, typename CumulativeCostFun>
- void ParallelFor(ContextImpl* context,
- int start,
- int end,
- int num_threads,
- F&& function,
- const CumulativeCostData* cumulative_cost_data,
- CumulativeCostFun&& cumulative_cost_fun) {
- CHECK_GT(num_threads, 0);
- if (start >= end) {
- return;
- }
- if (num_threads == 1 || end - start <= num_threads) {
- ParallelFor(context, start, end, num_threads, std::forward<F>(function));
- return;
- }
-
-
- constexpr int kNumPartitionsPerThread = 4;
- const int kMaxPartitions = num_threads * kNumPartitionsPerThread;
- const auto& partitions = PartitionRangeForParallelFor(
- start,
- end,
- kMaxPartitions,
- cumulative_cost_data,
- std::forward<CumulativeCostFun>(cumulative_cost_fun));
- CHECK_GT(partitions.size(), 1);
- ParallelFor(
- context, start, end, num_threads, std::forward<F>(function), partitions);
- }
- }
- #endif
|