内parallel_for时TBB spin_mutex阻止一个关键部分
问题描述:
概念,我怎么能阻止使用一个tbb::parallel_for
里面调用一个关键部分?关键部分少于20条指令,所以spin_mutex
是理想选择。例如下面的虚拟代码说明了情况:内parallel_for时TBB 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);
}
...
...
}
);
...
...
}
与泛函:
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()
作为成员函数
答
我只找到了解决这两个类之间没有基于类的继承。可能不是最佳的,但解决了我的问题。因此,将它作为可能遇到相同问题的人的答案发布。
基本上,解决方法是定义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
}
...
...
}
);
...
...
}
和泛函:
// 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
}
}
...
...
}
答
你可能要考虑使用静态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及更高版本(因为您需要“魔术静态”,即静态变量初始化的线程安全性)。