扩展线程运行时的c ++并发问题
Posted
技术标签:
【中文标题】扩展线程运行时的c ++并发问题【英文标题】:c++ concurrency issue with scaling thread runtime 【发布时间】:2016-12-10 23:02:34 【问题描述】:我有一个在大型数组上执行相同功能的程序。我将数组分成相等的块并将它们传递给线程。当前线程执行函数并返回它们应该执行的操作,但是我添加的线程越多,每个线程运行所需的时间就越长。这完全否定了并发的目的。我试过std::thread
和std::async
都得到相同的结果。在下面的图像中,所有子线程和主线程处理的数据量相同(主线程还有 6 个点),但是主线程在大约 12 秒内运行的数据量大约是线程数的 12 倍,就好像他们异步运行。但是它们都是同时开始的,如果我从每个线程输出它们是同时运行的。这与他们的加入方式有关吗?我已经尝试了我能想到的一切,非常感谢任何帮助/建议!在示例代码中,main 直到子线程完成后才运行该函数,如果我在 main 运行后放置 join,它仍然不会运行,直到子线程完成。下面您可以看到使用 3 和 5 个线程运行时的运行时。这些时间是在一个缩小的数据集上进行测试的。
void foo(char* arg1, long arg2, std::promise<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>> & ftrV)
std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>> Grid;
// does stuff....
// fills in "Grid"
ftrV.set_value(Grid);
int main()
int thnmb = 3; // # of threads
std::vector<long> buffers; // fill in buffers
std::vector<char*> pointers; //fill in pointers
std::vector<std::promise<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>>> PV(thnmb); // vector of promise grids
std::vector<std::future<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>>> FV(thnmb); // vector of futures grids
std::vector<std::thread> th(thnmb); // vector of threads
std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>> vt1(thnmb); // vector to store thread grids
for (int i = 0; i < thnmb; i++)
th[i] = std::thread(&foo, pointers[i], buffers[i], std::ref(PV[i]));
for (int i = 0; i < thnmb; i++)
FV[i] = PV[i].get_future();
for (int i = 0; i < thnmb; i++)
vt1[i] = FV[i].get();
for (int i = 0; i < thnmb; i++)
th[i].join();
// main performs same function as foo here
// combine data
// do other stuff..
return(0);
【问题讨论】:
您应该将命令窗口的内容复制并粘贴到问题中,而不是发布屏幕截图。 注意到@1201ProgramAlarm 【参考方案1】:如果不知道foo
做了什么,很难给出明确的答案,但您可能会遇到内存访问问题。每次访问您的 5 维数组都需要 5 次内存查找,并且只需要 2 或 3 个线程访问内存即可达到典型系统所能提供的饱和度。
main
应该在创建线程之后但在获得承诺值之前执行它的foo
工作。
并且foo
应该以ftrV.set_value(std::move(Grid))
结尾,这样就不必制作该数组的副本。
【讨论】:
谢谢!我相信您对内存访问问题是正确的。昨晚做了更多阅读后,我认为这可能与错误共享有关,但是每个线程正在访问的向量块的间隔比我的机器缓存线长 1000 倍,所以我不确定这是问题。我使用 5 维数组,因为以这种方式考虑我的数据集更直观(我知道它可能看起来不是这样),我可以通过一些更改将其分解为 2D 向量,这会减少内存查找成本? 如果您可以将其更改为更平坦的 2D 向量以上是关于扩展线程运行时的c ++并发问题的主要内容,如果未能解决你的问题,请参考以下文章