8

OpenMPを使用しており、フェッチアンドアッド操作を使用する必要があります。ただし、OpenMPは適切なディレクティブ/呼び出しを提供しません。最大限の移植性を維持したいので、コンパイラの組み込み関数に依存したくありません。

むしろ、OpenMPのアトミック操作を利用してこれを実装する方法を探していますが、行き止まりになっています。これもできますか?NB、次のコードはほとんど私が望むことをします:

#pragma omp atomic
x += a

ほとんど–ですが、完全ではありません。古い値の。が本当に必要だからですxfetch_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;
}

(コンペア・アンド・スワップについても同等の質問をすることができますが、私が間違っていなければ、一方を他方の観点から実装することができます。)

4

2 に答える 2

5

openmp 3.1以降、アトミック更新のキャプチャーがサポートされており、古い値または新しい値のいずれかをキャプチャーできます。とにかく値をインクリメントするにはメモリから値を取り込む必要があるため、たとえばCPUレジスタから値にアクセスしてスレッドプライベート変数に入れることができるのは理にかなっています。

gcc(またはg ++)を使用している場合は、優れた回避策があります。アトミックビルトインを検索してください:http: //gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

Intelの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
}

更新:IntelのC ++コンパイラを試しましたが、現在openmp 3.1をサポートしています(アトミックキャプチャが実装されています)。Intelは、非営利目的でLinuxでコンパイラを無料で使用できるようにしています。

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

GCC 4.7は、最終的にリリースされるときにopenmp3.1をサポートします...うまくいけばすぐに:)

于 2011-10-27T15:24:40.903 に答える
2

xの古い値を取得したいが、aが変更されていない場合は、古い値として(xa)を使用します。

fetch_and_add(int *x, int a) {
 #pragma omp atomic
 *x += a;

 return (*x-a);
}

更新:xは別のスレッドによってアトミック後に変更される可能性があるため、実際には答えではありませんでした。したがって、OMPプラグマを使用してユニバーサルな「フェッチアンドアッド」を作成することは不可能のようです。ユニバーサルとは、OMPコードのどこからでも簡単に使用できる操作を意味します。

関数を使用omp_*_lockして、アトミックをシミュレートできます。

typedef struct {omp_lock_t lock; int値;}atomic_simulated_t;

fetch_and_add(atomic_simulated_t *x, int a)
{
  int ret;
  omp_set_lock(x->lock);
  x->value +=a;
  ret = x->value;
  omp_unset_lock(x->lock);
}

これは醜くて遅いです(1ではなく2つのアトミック操作を実行します)。ただし、コードの移植性を高めたい場合は、すべての場合で最速とは限りません。

あなたは「次のように(非ロックのみ)」と言います。しかし、「非ロック」操作(CPUの「LOCK」プレフィックスまたはLL / SCなどを使用)とロック操作(いくつかのアトミック命令、ロック解除の短い待機のためのビジーループ、およびOSスリープで実装される)の違いは何ですか?長い間待つために)?

于 2010-11-17T17:25:20.370 に答える