这是我的用于TBB代码的原子计数器类。
#include <atomic>
template <typename T = int>
struct AtomicCounter {
private:
std::atomic<T> value;
std::atomic<T> num_inter;
public:
void put_inter(T niter) {
T x = num_inter.fetch_add(niter);
}
T get_inter() { return num_inter.load(); }
void increment() { ++value; }
void put(T data) { value.fetch_add(data) ; // ignore the old value returned }
void decrement() { --value; }
T get() { return value.load(); }
};
我正在使用并行的foreach循环,其中每个线程都有其自己的本地计数器值,并且它使用AtomicCounter类的put函数更新全局计数器对象。并行foreach的功能对象将此全局计数器作为参考。
template<typename counter_t>
struct my_functor {
public:
my_functor(){}
my_functor(counter_t &c):m_c(c){ }
template<typename label_t>
void operator()(label_t label) const {
// do some work --> local counter
m_c.put(local_value); // put the local counter value in the global counter
}
private:
counter_t& m_c;
mutable int local_value; //local counter value
}
// for TBB
//declare an object of this class as a global counter.
AtmoicCounter<int> c;
my_functor<atomicCounter<int>> func(c) //functor object
parallel_for_each( mywork.begin(), mywork.end(), func) //TBB parallel for each
因此,基本上,每个线程都会更新全局计数器。我在其中声明std :: atomic成员的atomicCounter类有什么问题吗?我正在使用具有C ++ 11功能和Intel TBB 4.2的GCC 4.7.2
谢谢!
我在声明中看不到任何问题。如果由于某种原因不确定使用GCC原子,请使用我确定使用的TBB原子。
但是我看到的问题是mutable
关键字的使用,以便从const
函子访问字段。mutable
通常是不良设计的标志。在并行编程中,它的用法特别容易出错。如果将并行调用的方法标记为const,则通常意味着将在functor类的同一实例上并行调用该方法。因此,您在可变字段上具有数据争用。
您可以将local_value移到的范围内operator()
,或者尝试使用线程本地容器tbb::combinable
或tbb::enumerable_thread_specific
缓存特定于线程的部分值,或者应用并行归约算法tbb::parallel_reduce
,以便将部分结果安全地存储在函子的正文中,而不用破坏const限制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句