首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >POSIX线程和O3优化

POSIX线程和O3优化
EN

Stack Overflow用户
提问于 2011-07-29 07:08:48
回答 2查看 345关注 0票数 0

我正在开发一个程序,它使用mpi (openmpi1.4.3)和pthread,在linux下的c++中工作。

一些mpi节点具有使用pthread实现的排队系统。Idea很简单,只有一个线程将元素添加到队列中,而其他几个“工作”线程拾取对象并在它们上做自己的工作(不是火箭科学)。

请考虑2个我的工作线程的例子,其中拾取元素。第一个示例工作正常,除非指定了-O3优化。在这种情况下,它开始无休止地循环,而没有拾取任何东西。

代码语言:javascript
复制
    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锁定。这项工作适用于所有级别的优化。

代码语言:javascript
复制
    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 );

    }

这就是我如何从其他线程填充队列,以防它有所不同

代码语言:javascript
复制
                    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选项进行编译?对排队系统还有其他建议吗?

非常感谢!

解决方案:这是我在最后提出的。似乎比上述任何一种方法都要好得多。(以防有人感兴趣;)

代码语言:javascript
复制
    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 );
        }




    }

添加

代码语言:javascript
复制
        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 )
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-07-29 07:16:12

当你检查队列是否为空时,我猜你看到的是一个基于指令排序假设的错误--当你打开优化时,排序会改变,它会中断,因为你拥有的互斥没有设置内存屏障来保护这种情况的发生。

票数 1
EN

Stack Overflow用户

发布于 2011-07-29 07:30:18

我很想在第一个空检查之前建议使用__sync_synchronize(),但这可能并不安全--如果另一个线程正在向容器添加内容,那么当您调用empty()时,该容器可能仍然处于不一致的状态。根据容器的不同,任何事情都可能发生,从返回错误的答案到崩溃。

Josh可能也是对的。锁定互斥锁还提供了内存屏障,这意味着您的代码将重新读取它正在使用的内存,以确定每次容器是否为空。如果没有某种类型的内存屏障,这种情况就永远不会发生,因此在更高的优化级别上,您的代码可能永远看不到变化。

另外,你有没有研究过pthread的condition variables?它们将允许您避免在循环中轮询,直到容器不再为空。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6866861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档