使用OpenMP原子操作的提取和添加 [英] Fetch-and-add using OpenMP atomic operations

查看:1552
本文介绍了使用OpenMP原子操作的提取和添加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是OpenMP,需要使用fetch-and-add操作。但是,OpenMP不提供适当的指令/调用。我想保持最大的可移植性,因此我不想依赖编译器内在性。

I’m using OpenMP and need to use the fetch-and-add operation. However, OpenMP doesn’t provide an appropriate directive/call. I’d like to preserve maximum portability, hence I don’t want to rely on compiler intrinsics.

相反,我在寻找一种方法来利用OpenMP的原子操作实现这一点,但我打了一个死胡同。这甚至可以做吗? NB,以下代码几乎做我想要的:

Rather, I’m searching for a way to harness OpenMP’s atomic operations to implement this but I’ve hit a dead end. Can this even be done? N.B., the following code almost does what I want:

#pragma omp atomic
x += a

几乎 - 但不完全,因为我真的需要 x fetch_and_add 应定义为产生与以下(仅非锁定)相同的结果:

Almost – but not quite, since I really need the old value of x. fetch_and_add should be defined to produce the same result as the following (only non-locking):

template <typename T>
T fetch_and_add(volatile T& value, T increment) {
    T old;
    #pragma omp critical
    {
        old = value;
        value += increment;
    }
    return old;
}

(可以要求一个等效的问题进行比较和交换, )

(An equivalent question could be asked for compare-and-swap but one can be implemented in terms of the other, if I’m not mistaken.)

推荐答案

由于openmp 3.1支持捕获原子更新,可以捕获旧值或新值。因为我们必须将内存中的值增加,所以我们应该能够从一个CPU寄存器访问它,并将其放入一个线程私有变量。

As of openmp 3.1 there is support for capturing atomic updates, you can capture either the old value or the new value. Since we have to bring the value in from memory to increment it anyways, it only makes sense that we should be able to access it from say, a CPU register and put it into a thread-private variable.

有一个很好的解决方法,如果你使用gcc(或g ++),查找原子内建:
http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

There's a nice work-around if you're using gcc (or g++), look up atomic builtins: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

它认为英特尔的C / C ++编译器也支持这个,但我没有尝试过。

It think Intel's C/C++ compiler also has support for this but I haven't tried it.

现在(直到openmp 3.1被实现),我在C ++中使用了内联包装函数,你可以在编译时选择使用哪个版本:

For now (until openmp 3.1 is implemented), I've used inline wrapper functions in C++ where you can choose which version to use at compile time:

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
}



更新:我刚刚试过Intel的C ++编译器目前已经支持openmp 3.1(原子捕获实现)。英特尔在linux中为非商业目的免费使用其编译器:

Update: I just tried Intel's C++ compiler, it currently has support for openmp 3.1 (atomic capture is implemented). Intel offers free use of its compilers in linux for non-commercial purposes:

http://software.intel.com/en-us/articles/non-commercial-software-download/

GCC 4.7将支持openmp 3.1,当它最终被释放...希望很快:)

GCC 4.7 will support openmp 3.1, when it eventually is released... hopefully soon :)

这篇关于使用OpenMP原子操作的提取和添加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆