我想重用一个线程 vector ,这些线程使用不同的参数多次调用同一函数。没有写入(原子参数除外),因此不需要互斥体。为了描述这个想法,我创建了一个并行代码的基本示例,用于查找 vector 的最大值。显然有更好的方法来找到 vector 的最大值,但为了解释并避免深入了解我正在编写的实际代码的更多细节,我将使用这个愚蠢的示例。
代码通过调用函数pFind来查找 vector 的最大数量,该函数检查 vector 是否包含数字k(k是初始化为上限)。如果是,则执行停止,否则k减一并重复该过程。
下面的代码生成一个线程 vector ,并行化 vector 中k的搜索。问题是,对于 k 的每个值,每次连接新线程时都会重新生成线程 vector 。 生成线程 vector 并每次连接它们都会带来我想避免的开销。
我想知道是否有一种方法只生成一次线程 vector (池)并将其重用于新的执行。任何其他加速技巧将不胜感激。
void pFind(
vector<int>& a,
int n,
std::atomic<bool>& flag,
int k,
int numTh,
int val
) {
int i = k;
while (i < n) {
if (a[i] == val) {
flag = true;
break;
} else
i += numTh;
}
}
int main() {
std::atomic<bool> flag;
flag = false;
int numTh = 8;
int val = 1000;
int pos = 0;
while (!flag) {
vector<thread>threads;
for (int i = 0; i < numTh; i++){
thread th(&pFind, std::ref(a), size, std::ref(flag), i, numTh, val);
threads.push_back(std::move(th));
}
for (thread& th : threads)
th.join();
if (flag)
break;
val--;
}
cout << val << "\n";
return 0;
}
最佳答案
构造后无法为 std::thread
分配不同的执行函数(闭包)。对于所有线程抽象来说,这通常都是正确的,尽管实现通常会尝试在内部内存或缓存较低级别的抽象,以使线程快速 fork 和连接,因此仅构造新线程是可行的。系统编程界有一个争论,即创建一个新线程是否应该非常轻量级,或者客户端是否应该被编写为不那么频繁地 fork 线程。 (考虑到这种情况已经持续了很长一段时间,很明显涉及到很多权衡。)
还有很多其他抽象试图做你真正想做的事情。它们的名称包括“线程池”、“任务执行器”(或只是“执行器”)和“futures”。所有这些都倾向于通过创建一些线程集(通常与系统中的硬件核心数量相关)来映射到线程,然后让每个线程循环并查找请求。
正如评论所指出的,您自己执行此操作的主要方法是让线程具有顶级循环,该循环接受执行请求,处理它们,然后发布结果。为此,您需要使用其他同步方法,例如互斥体和条件变量。如果有很多请求并且请求不是非常大,那么通常以这种方式执行操作会更快。
尽管标准 C++ 并发支持是一件好事,但对于现实世界的高性能工作来说,它也相当缺乏。类似于 Intel's TBB更像是一种工业强度的解决方案。
关于C++ 重用调用同一函数的线程 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47171107/