我对现代C ++库很陌生,并试图学习如何使用std :: async在大指针数组上执行某些操作。我编写的示例代码在异步任务启动时崩溃。
示例代码:
#include <iostream>
#include <future>
#include <tuple>
#include <numeric>
#define maximum(a,b) (((a) > (b)) ? (a) : (b))
class Foo {
bool flag;
public:
Foo(bool b) : flag(b) {}
//******
//
//******
std::tuple<long long, int> calc(int* a, int begIdx, int endIdx) {
long sum = 0;
int max = 0;
if (!(*this).flag) {
return std::make_tuple(sum, max);
}
if (endIdx - begIdx < 100)
{
for (int i = begIdx; i < endIdx; ++i)
{
sum += a[i];
if (max < a[i])
max = a[i];
}
return std::make_tuple(sum, max);
}
int midIdx = endIdx / 2;
auto handle = std::async(&Foo::calc, this, std::ref(a), midIdx, endIdx);
auto resultTuple = calc(a, begIdx, midIdx);
auto asyncTuple = handle.get();
sum = std::get<0>(asyncTuple) +std::get<0>(resultTuple);
max = maximum(std::get<1>(asyncTuple), std::get<1>(resultTuple));
return std::make_tuple(sum, max);
}
//******
//
//******
void call_calc(int*& a) {
auto handle = std::async(&Foo::calc, this, std::ref(a), 0, 10000);
auto resultTuple = handle.get();
std::cout << "Sum = " << std::get<0>(resultTuple) << " Maximum = " << std::get<1>(resultTuple) << std::endl;
}
};
//******
//
//******
int main() {
int* nums = new int[10000];
for (int i = 0; i < 10000; ++i)
nums[i] = rand() % 10000 + 1;
Foo foo(true);
foo.call_calc(nums);
delete[] nums;
}
任何人都可以帮我确定它崩溃的原因吗? 有没有更好的方法将并行性应用于大指针数组上的操作?
答案 0 :(得分:1)
根本问题是你的代码想要启动超过数组大小/ 100个线程。这意味着超过100个线程。 100个线程不会做任何好事;他们会捶打。请参阅std::thread::hardware_concurrency
,通常不要在生产应用中使用原始async
或thread
;写任务池并将期货等拼接在一起。
许多线程都非常低效并且可能耗尽系统资源。
第二个问题是你无法计算2个值的平均值。
begIdx
和endIdx
的平均值不是endIdx/2
,而是:
int midIdx = begIdx + (endIdx-begIdx) / 2;
您会注意到我通过添加中间输出发现了程序的问题。特别是,我打印出它正在处理的范围,我注意到它是重复范围。这被称为“printf调试”,并且功能非常强大,特别是当基于步骤的调试不是这种情况时(通过这么多线程,逐步执行代码会让人麻木)
答案 1 :(得分:1)
异步调用的问题在于,在某些可以完全同时执行无限任务的Universe中没有完成它们。
在具有一定数量处理器/核心的处理器上执行异步调用,并且必须排列异步调用以在其上执行。
现在,这里出现同步问题,阻塞,饥饿等问题以及其他多线程问题。
您的算法非常难以遵循,因为它在已创建的任务中生成任务。有些事情正在发生,但很难遵循。
我会通过以下方式解决这个问题: