【发布时间】:2017-07-04 03:23:48
【问题描述】:
注意:这是我在此网站上发表的第一篇文章,但我进行了广泛搜索,但无法找到解决问题的方法。 我编写了一个程序,它基本上测试数字向量的所有排列,以找到我定义的最佳序列。当然,即使是小的输入,计算数字的排列也是非常耗时的,所以我试图通过使用多线程来加快速度。
这是一个复制问题的小样本:
class TaskObject {
public:
void operator()() {
recursiveFunc();
}
private:
Solution *bestSolution; //Shared by every TaskObject, but can only be accessed by one at a time
void recursiveFunc() {
if (base_case) {
//Only part where shared object is accessed
//base_case is rarely reached
return;
}
recursiveFunc();
}
};
void runSolutionWithThreads() {
vector<thread> threads(std::thread::hardware_concurrency());
vector<TaskObject> tasks_vector(std::thread::hardware_concurrency());
updateTasks(); //Sets parameters that intialize the first call to recursiveFunc
for (int q = 0; q < (int)tasks_vector.size(); ++q) {
threads[q] = std::thread(tasks_vector[q]);
}
for (int i = 0; i < (int)threads.size(); ++i) {
threads[i].join();
}
}
我以为这将使所有线程能够并行运行,但我可以看到使用 Visual Studio 中的性能分析器和 Windows 任务管理器的高级设置,一次只运行 1 个线程。在可以访问 4 个线程的系统上,CPU 限制在 25%。 每次运行时我都会得到正确的输出,因此算法逻辑没有问题。工作尽可能均匀地分布在所有任务对象中。很少发生与共享数据的冲突。使用线程池的程序实现总是以接近 100% 的速度运行。
提交给线程的对象不会打印到 cout,并且除了它们都通过指针引用的一个共享对象之外,它们都有自己的数据副本来执行它们的工作。
private:
Solution* bestSolution;
此共享数据不易受到数据竞争条件的影响,因为我使用互斥锁中的 lock_guard 来制作它,因此一次只有一个线程可以更新 bestSolution。
换句话说,我的多线程程序使用系统中可用的线程数,为什么我的 CPU 没有以接近 100% 的速度运行?
如果需要,我可以随时更新这篇文章,提供更多信息。
【问题讨论】:
-
您可能需要minimal reproducible example,而您的共享对象看起来非常怀疑是数据竞争
-
@PasserBy 共享对象不应受到数据竞争条件的影响。
-
代码还不完整,经验法则是有人应该能够复制粘贴某些内容并查看您的结果。这并不是说你应该把所有的东西都塞进去,这意味着你应该模拟
Solution及其以某种方式访问它仍然可以复制问题。如果您后来意识到问题与Solution的工作方式有关,那么您可能已经解决了问题。
标签: c++ multithreading concurrency parallel-processing thread-synchronization