1

我正在关注本教程以了解如何使用 VTUNE 删除锁
此页面在收集 Vtune 结果后显示以下内容:

识别最热门的代码行

单击热点导航按钮转到等待时间最长的代码行。VTune Amplifier 突出显示进入 draw_task 函数中临界区 rgb_critical_section 的第 170 行。draw_task 函数在此代码行执行期间等待了将近 27 秒,并且大部分时间处理器未得到充分利用。在此期间,临界区被争用了 438 次。

rgb_critical 部分是应用程序序列化的地方。每个线程必须等待关键部分可用才能继续。一次只能有一个线程位于临界区。您需要优化代码以使其更具并发性。

在我到达下一部分之前,我能够按照本教程进行操作:移除锁

取下锁

引入 rgb_critical_section 是为了保护计算免受多线程访问。简要分析表明,代码是线程安全的,临界区并不是真正需要的。

我的问题是我们怎么知道代码是线程安全的?

正如建议的那样,我评论了那些行(EnterCritical ...和LeaveCritical ...),并看到了巨大的性能提升,但我不明白为什么不需要这个关键部分?哪项分析告诉我们这一点?

相关代码在analyze_locks.cpp中:

public:
    void operator () (const tbb::blocked_range <int> &r) const {

        unsigned int serial = 1;
        unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
        unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
        memset(local_mbox,0,mboxsize);

        for (int y=r.begin(); y!=r.end(); ++y) {
            drawing_area drawing(startx, totaly-y, stopx-startx, 1);

            // Enter Critical Section to protect pixel calculation from multithreaded access (Needed?)
        //  EnterCriticalSection(&rgb_critical_section);

            for (int x = startx; x < stopx; x++) {
                color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy);
                drawing.put_pixel(c);
            }

            // Exit from the critical section
        //  LeaveCriticalSection(&rgb_critical_section);

            if(!video->next_frame()) tbb::task::self().cancel_group_execution();
        }
    }

    draw_task () {}

};
4

1 回答 1

1

如果没有全局状态(即该特定线程之外的状态)被修改,则某些东西是线程安全的。我们很难说出实际做了什么,render_one_pixel以及drawing.put_pixel可能需要以什么顺序执行。

假设调用的顺序put_pixel(c)无关紧要(或哪个线程进行调用),在这里删除临界区是安全的。如果需要严格的排序,我不确定关键部分是否是正确的解决方案。(同样的规则显然适用于render_one_pixel,如果它改变了一些全局状态,这当然也必须在“是否安全”中考虑在内)。

于 2013-11-19T15:07:43.490 回答