Kon*_*lph 8 c++ atomic openmp compare-and-swap
我正在使用OpenMP,需要使用fetch-and-add操作.但是,OpenMP不提供适当的指令/调用.我想保留最大的可移植性,因此我不想依赖编译器内在函数.
相反,我正在寻找一种方法来利用OpenMP的原子操作来实现这一点,但我已经走到了尽头.甚至可以这样做吗?注意,以下代码几乎可以满足我的需求:
#pragma omp atomic
x += a
Run Code Online (Sandbox Code Playgroud)
几乎 - 但不完全,因为我真的需要旧的价值x.fetch_and_add应定义为产生与以下相同的结果(仅非锁定):
template <typename T>
T fetch_and_add(volatile T& value, T increment) {
T old;
#pragma omp critical
{
old = value;
value += increment;
}
return old;
}
Run Code Online (Sandbox Code Playgroud)
(如果我没有弄错的话,可以要求一个等价的问题进行比较和交换,但可以用另一个来实现.)
从 openmp 3.1 开始,支持捕获原子更新,您可以捕获旧值或新值。因为无论如何我们都必须从内存中引入该值来增加它,所以我们应该能够从 CPU 寄存器访问它并将其放入线程私有变量中才有意义。
如果您使用 gcc(或 g++),有一个很好的解决方法,查找原子内置函数:http : //gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html
它认为英特尔的 C/C++ 编译器也支持这一点,但我还没有尝试过。
目前(在实现 openmp 3.1 之前),我在 C++ 中使用了内联包装函数,您可以在其中选择在编译时使用的版本:
template <class T>
inline T my_fetch_add(T *ptr, T val) {
#ifdef GCC_EXTENSION
return __sync_fetch_and_add(ptr, val);
#endif
#ifdef OPENMP_3_1
T t;
#pragma omp atomic capture
{ t = *ptr; *ptr += val; }
return t;
#endif
}
Run Code Online (Sandbox Code Playgroud)
更新:我刚刚尝试了英特尔的 C++ 编译器,它目前支持 openmp 3.1(实现了原子捕获)。英特尔提供在 linux 中免费使用其编译器用于非商业目的:
http://software.intel.com/en-us/articles/non-commercial-software-download/
GCC 4.7 将支持 openmp 3.1,当它最终发布时......希望很快:)
| 归档时间: |
|
| 查看次数: |
6046 次 |
| 最近记录: |