gpt4 book ai didi

c++ - 多线程效率不高 : Debugging False Sharing?

转载 作者:行者123 更新时间:2023-11-30 03:55:38 24 4
gpt4 key购买 nike

我有以下代码,它在一开始就启动了多个线程(一个线程池)(startWorkers())。随后,在某个时候,我有一个装满 myWorkObject 实例的容器,我想同时使用多个工作线程来处理它。 myWorkObject 在内存使用方面完全相互隔离。现在让我们假设 myWorkObject 有一个方法 doWorkIntenseStuffHere() 需要一些 cpu 时间来计算。

在对以下代码进行基准测试时,我注意到该代码不能很好地扩展线程数,并且初始化/同步工作线程的开销超过了多线程的好处,除非有 3-4 个线程处于事件状态。我调查了这个问题并阅读了有关虚假共享问题的信息,我认为我的代码遇到了这个问题。但是,我想调试/分析我的代码以查看是否存在某种饥饿/错误共享。我怎样才能做到这一点?请随意批评我的代码,因为我仍在学习很多关于内存/cpu 和多线程的知识。

#include <boost/thread.hpp>

class MultiThreadedFitnessProcessingStrategy
{
public:
MultiThreadedFitnessProcessingStrategy(unsigned int numWorkerThreads):
_startBarrier(numWorkerThreads + 1),
_endBarrier(numWorkerThreads + 1),
_started(false),
_shutdown(false),
_numWorkerThreads(numWorkerThreads)
{
assert(_numWorkerThreads > 0);
}


virtual ~MultiThreadedFitnessProcessingStrategy()
{
stopWorkers();
}


void startWorkers()
{
_shutdown = false;
_started = true;

for(unsigned int i = 0; i < _numWorkerThreads;i++)
{
boost::thread* workerThread = new boost::thread(
boost::bind(&MultiThreadedFitnessProcessingStrategy::workerTask, this,i)
);
_threadQueue.push_back(new std::queue<myWorkObject::ptr>());
_workerThreads.push_back(workerThread);
}
}


void stopWorkers()
{
_startBarrier.wait();
_shutdown = true;
_endBarrier.wait();

for(unsigned int i = 0; i < _numWorkerThreads;i++)
{
_workerThreads[i]->join();
}

}

void workerTask(unsigned int id)
{

//Wait until all worker threads have started.
while(true)
{
//Wait for any input to become available.
_startBarrier.wait();

bool queueEmpty = false;
std::queue<SomeClass::ptr >* myThreadq(_threadQueue[id]);

while(!queueEmpty)
{

SomeClass::ptr myWorkObject;

//Make sure queue is not empty,
//Caution: this is necessary if start barrier was triggered without queue input (e.g., shutdown) , which can happen.
//Do not try to be smart and refactor this without knowing what you are doing!
queueEmpty = myThreadq->empty();


if(!queueEmpty)
{
chromosome = myThreadq->front();
assert(myWorkObject);
myThreadq->pop();
}

if(myWorkObject)
{
myWorkObject->doWorkIntenseStuffHere();
}
}

//Wait until all worker threads have synchronized.
_endBarrier.wait();

if(_shutdown)
{
return;
}
}
}


void doWork(const myWorkObject::chromosome_container &refcontainer)
{

if(!_started)
{
startWorkers();
}

unsigned int j = 0;
for(myWorkObject::chromosome_container::const_iterator it = refcontainer.begin();
it != refcontainer.end();++it)
{
if(!(*it)->hasFitness())
{
assert(*it);
_threadQueue[j%_numWorkerThreads]->push(*it);
j++;
}
}

//Start Signal!
_startBarrier.wait();

//Wait for workers to be complete
_endBarrier.wait();

}


unsigned int getNumWorkerThreads() const
{
return _numWorkerThreads;
}

bool isStarted() const
{
return _started;
}


private:

boost::barrier _startBarrier;
boost::barrier _endBarrier;

bool _started;
bool _shutdown;

unsigned int _numWorkerThreads;

std::vector<boost::thread*> _workerThreads;

std::vector< std::queue<myWorkObject::ptr >* > _threadQueue;


};

最佳答案

基于抽样的分析可以让您很好地了解自己是否遇到了虚假共享。这是一个 previous thread描述了解决该问题的几种方法。我认为该线程没有提到 Linux 的 perf utility .这是一种快速、简单且免费的计算缓存未命中数的方法,它可能会告诉您您需要了解的信息(我是否遇到了大量与我访问特定变量的次数相关的缓存未命中数?)。

如果您确实发现您的线程方案可能导致大量冲突遗漏,您可以尝试声明您的 myWorkObject 实例或其中包含您实际关心的数据 __attribute__((aligned(64 )))(与 64 字节缓存行对齐)。

关于c++ - 多线程效率不高 : Debugging False Sharing?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28961637/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com