我正在尝试并行化数组计算,因此,我建立了一个具有Worker(内部)类的Shader(外部)类。外部类接收一个数组及其大小,然后继续在Workers的新实例之间进行划分。 它创建一个工作器向量,然后创建一个分配了工作器函数的线程向量。 不幸的是,该应用程序因段崩溃。错误并使用调试器,我已经确认一些对象没有实例化(而有些实际上是实例化)并且缺少必需的数据。 由于实例化不是并行进行的,因此不应存在任何竞争条件。
我正在使用mingw_64作为编译器。其他库为<iostream>,<c++/4.8.3/sstream>,<math.h>,<SDL.h>,<SDL_image.h>,<thread>,<vector>
。
外部类的主要功能:
void BlurShader::render()
{
int threadsNum;
for (threadsNum = 6; threadsNum > 1; threadsNum--)
{
if (height % threadsNum == 0) break;
}
int heightStep = height / threadsNum;
auto *workerObjects = new vector<Worker*>;
auto *workerThreads = new vector<thread *>;
// Instantiating workers:
for (int i = 0; i < threadsNum; i++)
{
workerObjects->push_back(
new Worker(this->original, this->palette, this->width, this->height,
i * heightStep,((i + 1) * heightStep) - 1));
}
/* As you can see a lot of information is streamed into the worker,
and it is relying on it. Then in a second for loop I create
threads: */
for (int i = 0; i < threadsNum; i++)
{
workerThreads->push_back(new thread([&]()
{
(*workerObjects)[i]->threadProcess();
}));
}
// Then the main thread waits for threads to finish:
for (int j = 0; j < threadsNum; j++)
{
(*workerThreads)[j]->join();
delete (*workerThreads)[j];
}
// Cleanup
for(int i=0;i<threadsNum;i++)
{
delete (*workerObjects)[i];
}
delete workerObjects;
delete workerThreads;
memcpy(original, palette, height * width * size);
}
期待您的建议。 如果发现我没有正确使用线程,我将很乐意听。我只有一个星期会使用C ++,所以一切都会顺利进行。
答案 0 :(得分:0)
问题在于lambda捕获i
的方式:
for (int i = 0; i < threadsNum; i++)
{
workerThreads->push_back(new thread([&]() // [1]
{
(*workerObjects)[i]->threadProcess();
}));
}
i
被引用捕获,但是您不知道线程的主体(即闭包)何时被调用,因此i
可能已被修改(通过 for 循环)在读取正确的i
值之前。
通过副本传递i
:
for (int i = 0; i < threadsNum; i++)
{
workerThreads->push_back(new thread([&,i]() // pass i by copy
{
(*workerObjects)[i]->threadProcess();
}));
}