我正在开发一个程序,它使用mpi (openmpi1.4.3)和pthread,在linux下的c++中工作。
一些mpi节点具有使用pthread实现的排队系统。Idea很简单,只有一个线程将元素添加到队列中,而其他几个“工作”线程拾取对象并在它们上做自己的工作(不是火箭科学)。
请考虑2个我的工作线程的例子,其中拾取元素。第一个示例工作正常,除非指定了-O3优化。在这种情况下,它开始无休止地循环,而没有拾取任何东西。
while (true){
if (t_exitSignal[tID]){
dorun = false;
break;
}
//cout<<"w8\n";
//check if queue has some work for us
if (!frame_queue->empty()){
//try to get lock and recheck that queue no empty
pthread_mutex_lock( &mutex_frame_queue );
if (!frame_queue->empty()){
cout<<"Pickup "<<tID<<endl;
con = frame_queue->front();
frame_queue->pop();
t_idling[tID] = false;
pthread_mutex_unlock( &mutex_frame_queue );
break;
}
pthread_mutex_unlock( &mutex_frame_queue );
}
}现在考虑这个,完全相同的代码,除了在我检查queue->empthy之前的mutex gettimg锁定。这项工作适用于所有级别的优化。
while (true){
if (t_exitSignal[tID]){
dorun = false;
break;
}
//cout<<"w8\n";
//try to get lock and recheck that queue no empty
pthread_mutex_lock( &mutex_frame_queue );
//check if queue has some work for us
if (!frame_queue->empty()){
cout<<"Pickup "<<tID<<endl;
con = frame_queue->front();
frame_queue->pop();
t_idling[tID] = false;
pthread_mutex_unlock( &mutex_frame_queue );
break;
}
pthread_mutex_unlock( &mutex_frame_queue );
}这就是我如何从其他线程填充队列,以防它有所不同
pthread_mutex_lock( &mutex_frame_queue );
//adding the same contianer into queue to make it available for threads
frame_queue->push(*cursor);
pthread_mutex_unlock( &mutex_frame_queue );我的问题是:为什么第一个代码示例停止工作,为什么我使用-O3选项进行编译?对排队系统还有其他建议吗?
非常感谢!
解决方案:这是我在最后提出的。似乎比上述任何一种方法都要好得多。(以防有人感兴趣;)
while (true){
if (t_exitSignal[tID]){
dorun = false;
break;
}
//try to get lock and check that queue no empty
pthread_mutex_lock( &mutex_frame_queue );
if (!frame_queue->empty()){
con = frame_queue->front();
frame_queue->pop();
t_idling[tID] = false;
pthread_mutex_unlock( &mutex_frame_queue );
break;
}else{
pthread_cond_wait(&conf_frame_queue, &mutex_frame_queue);
pthread_mutex_unlock( &mutex_frame_queue );
}
}添加
pthread_mutex_lock( &mutex_frame_queue );
//adding the same contianer into queue to make it available for threads
frame_queue->push(*cursor);
//wake up any waiting threads
pthread_cond_signal(&conf_frame_queue);
pthread_mutex_unlock( &mutex_frame_queue )发布于 2011-07-29 07:16:12
当你检查队列是否为空时,我猜你看到的是一个基于指令排序假设的错误--当你打开优化时,排序会改变,它会中断,因为你拥有的互斥没有设置内存屏障来保护这种情况的发生。
发布于 2011-07-29 07:30:18
我很想在第一个空检查之前建议使用__sync_synchronize(),但这可能并不安全--如果另一个线程正在向容器添加内容,那么当您调用empty()时,该容器可能仍然处于不一致的状态。根据容器的不同,任何事情都可能发生,从返回错误的答案到崩溃。
Josh可能也是对的。锁定互斥锁还提供了内存屏障,这意味着您的代码将重新读取它正在使用的内存,以确定每次容器是否为空。如果没有某种类型的内存屏障,这种情况就永远不会发生,因此在更高的优化级别上,您的代码可能永远看不到变化。
另外,你有没有研究过pthread的condition variables?它们将允许您避免在循环中轮询,直到容器不再为空。
https://stackoverflow.com/questions/6866861
复制相似问题