并行内部TBB spin_mutex用于阻止临界区

时间:2017-08-24 18:16:16

标签: c++ multithreading mutex tbb thread-synchronization

从概念上讲,如何使用tbb::parallel_for阻止tbb:spin_mutex来电中的关键部分?关键部分少于20条指令,因此spin_mutex是理想的。例如,以下虚拟代码解释了这种情况:

function() {
    // I'm using lambda functions in parallel_for call here. The parallel_for 
    // is multithreading across the size of the vector customVec
    tbb::parallel_for(
        tbb::blocked_range<vector<CustomeType>::iterator>(customVec.begin(), customVec.end(), 1), 
        [&](tbb::blocked_range<vector<CustomType>::iterator> customVec) {
            for (vector<CustomType>::iterator it = customVec.begin(); it != customVec.end(); it++) {
                CustomType item = *it;
                ...
                ...

                // This is the cross-functional call that each thread will call
                // critical section is in-side the functionA
                item->functionA(param1, param2);
            }

            ...
            ...   
        }
    );

    ...
    ...
}

功能A:

functionA (Type1 param1, Type2 param2) {
    if (conditionX) {
        /* This file read is the critical section. So basically, need to 
        block multiple threads reading the same file to reduce I/O cost
        and redundancy. Since file read can be stored in a global variable
        that can be accessed in memory by other threads */

        fileRead(filename); // Critical line that need to be protected
    }
    ...
    ...
}

我正在努力解决的问题是我如何在spin_mutex中设置functionA(),以便在整个线程中共享mutex,并且线程不会超越对方尝试执行关键部分同时进行。

注意:假设function()functionA()属于两个单独的C ++类,并且在function()functionA()为成员的两个类之间没有基于类的继承功能

2 个答案:

答案 0 :(得分:1)

您可能需要考虑在函数中使用静态spin_mutex

functionA (Type1 param1, Type2 param2) {
    if (conditionX) {
        /* This file read is the critical section. So basically, need to 
        block multiple threads reading the same file to reduce I/O cost
        and redundancy. Since file read can be stored in a global variable
        that can be accessed in memory by other threads */

        // A static mutex that is shared across all invocations of the function.
        static tbb::spin_mutex mtx;
        // Acquire a lock 
        tbb::spin_mutex::scoped_lock lock(mtx);
        fileRead(filename); // Critical line that need to be protected
    }
    ...
    ...
}

注意它只适用于C ++ 11及更高版本(因为你需要&#34; magic static&#34;,即静态变量初始化的线程安全性)。

答案 1 :(得分:0)

我刚刚找到了解决方案。可能不是最优,但解决了我的问题。因此,将其作为可能遇到同一问题的人的答案发布。

基本上,解决方案是在spin_mutex之外定义parallel_for对象,并将其作为参考传递给函数调用。我已经使用以下解决方案在问题中发布了相同的代码示例:

tbb::spin_mutex mtx;   // Declare spin_mutex object
function() {
    // I'm using lambda functions in parallel_for call here. The parallel_for 
    // is multithreading across the size of the vector customVec
    tbb::parallel_for(
        tbb::blocked_range<vector<CustomeType>::iterator>(customVec.begin(), customVec.end(), 1), 
        [&](tbb::blocked_range<vector<CustomType>::iterator> customVec) {
            for (vector<CustomType>::iterator it = customVec.begin(); it != customVec.end(); it++) {
                CustomType item = *it;
                ...
                ...

                // This is the cross-functional call that each thread will call
                // critical section is in-side the functionA
                item->functionA(param1, param2, mtx);   // pass object as a reference
            }

            ...
            ...   
        }
    );

    ...
    ...
}

和functionA:

// Pass the spin_mutex object by reference
functionA (Type1 param1, Type2 param2, tbb::spin_mutex& mtx) {
    if (conditionX) {
        /* This file read is the critical section. So basically, need to 
        block multiple threads reading the same file to reduce I/O cost
        and redundancy. Since file read can be stored in a global variable
        that can be accessed in memory by other threads */

        // Acquire a scope lock 
        { 
            tbb::spin_mutex::scoped_lock lock(mtx);
            fileRead(filename); // Critical line that need to be protected
        }
    }
    ...
    ...
}