1

注意:这是我在此网站上发布的第一篇文章,但我已经广泛搜索,无法找到解决问题的方法。 我写了一个程序,它主要测试一个数字向量的所有排列,以找到我定义的最佳序列。当然,即使对于小输入来说,计算数字排列也是非常耗时的,所以我试图通过使用多线程来加快速度。并行运行的多线程C++程序使用矢量<thread>和.join()


这里是一个小样本,其复制的问题:

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,并且除了一个共享对象(它们全都通过指针引用)之外,它们都有自己的执行工作所需的数据副本。因为我lock_guard用于从互斥使它所以只有一个线程可以一次更新bestSolution

private: 
    Solution* bestSolution; 

此共享的数据是不容易受到数据竞争条件。

换句话说,为什么我的CPU在我的多线程程序中几乎100%运行,它使用了系统中可用的多个线程?

我可以随时更新这篇文章,如果需要更多的信息。

+1

您可能需要[mcve],并且您的共享对象看起来高度怀疑是数据竞赛 –

+0

@PasserBy共享对象不应受数据竞争条件的影响。 –

+0

代码还不完整,根据经验,有人应该能够复制粘贴某些内容并查看结果。这并不是说你应该把所有东西都放在这里,这意味着你应该以某种方式嘲笑'解决方案'和它的访问,这仍然可以复制问题。如果您后来意识到问题与“解决方案”的工作方式有关,那么您可能已经解决了这个问题。 –

回答

2

在调试你的应用程序时,使用调试器来“断开所有”线程。然后用调试线程窗口检查每个线程,以查看每个线程正在执行的位置。很可能你会发现只有一个线程正在执行代码,而其余的都被阻塞在一个正在运行的线程持有的互斥体上。

如果您展示了一个更完整的代码示例,它可以提供极大的帮助。

+0

我更新了这篇文章,注意到很少发生与共享数据的冲突。在调试器中,似乎所有线程都以大致相同的速度工作,但在我的4个线程系统中,CPU在性能分析器中的使用率为25%。我知道肯定有一个错误,因为当我使用线程池实现运行程序时,我发现程序几乎总是处于100%的CPU利用率。 –