给出以下代码,执行非常简单的任务:
for (int i = 0; i < 181; i++)
{
for (int j = 0; j < 360; j++)
{
if (Arr[i][j] > Max)
{
Max = Arr[i][j];
MaxPosition[0] = i;
MaxPosition[1] = j;
}
}
}
并且假设使用mutex
es比花费更多的时间,那么在并行循环中是否还有其他可能性?我可以考虑atomic
和combinable
来查找Max
的值,但不要在Arr
数组中获取它的位置。
答案 0 :(得分:1)
如果你有X个并行线程,每个都检查一个Arr
的小分区,那么你可以拥有X MaxPosition
数组和一个X Max
数组。然后,当并行线程全部完成时,您有一个小循环,使用Max
数组中的位置从MaxPosition
数组中找出最终的最大值。
简单示例:
void thread_function(int start_x, int end_x,
std::vector<std::vector<int>> const& arr,
int& max_value,
std::pair<int, int>& max_position)
{
max_value = std::numeric_limits<int>::min();
for (int x = start_x; x < end_x; ++x)
{
for (int y = 0; y < 360; ++y)
{
if (arr[x][y] > max_value)
{
max_value = arr[x][y];
max_positions.first = x;
max_positions.second = y;
}
}
}
}
现在该如何使用
std::vector<std::vector<int>> arr; // The array of numbers, filled with values somehow...
constexpr size_t number_of_threads = 4;
std::vector<int> max_values(number_of_threads);
std::vector<std::pair<int, int>> max_positions(number_of_threads);
// Initial values
int start_x = 0;
int end_x = arr.size() / number_of_threads;
std::vector<std::thread> threads;
for (int i = 0; i < number_of_threads; ++i)
{
threads.emplace_back(thread_function,
start_x, start_y, std::cref(arr),
std::ref(max_values[i]),
std::ref(max_positions[i]));
}
// Wait for threads to finish
for (int i = 0; i < number_of_threads; ++i)
{
threads[i].join();
}
// Now max_values contains the max value for each thread
// and max_positions contains the positions for that value from each thread
// Collate the data
auto iter_pos = std::max_element(begin(max_values), end(max_values));
int max_value = *iter_pos;
std::pair<int, int> max_position = max_positions[std::distance(begin(max_values), iter_pos)];
std::cout << "The max value is " << max_value << ", and it is found as position <" << max_position.first << ',' << max_position.second << ">\n";
<强> 注意: 强>
上述代码要求“{1”}中“第一”维度中的元素数量均匀分割。number_of_threads
。例如,180
可以使用,但不能181
。我会把它作为练习留给读者解决。
有关所用类和函数的参考,请参阅例如this superb online C++ reference