17

マルチコアx86マシンでは、core1で実行されているスレッドが整数変数aをインクリメントすると同時に、コア2のスレッドも整数変数をインクリメントするとします。の初期値aが0だったとすると、それは常に2最後になりますか?それとも他の価値があるのでしょうか?aとして宣言されてvolatileおり、アトミック変数(C++のatomic<>やgccの組み込みアトミック操作など)を使用していないと仮定します。

そのようなイベントでの値aが実際に常に2である場合、それlong intはx86-64のaも同じプロパティを持つことを意味しますか、つまりa、最終的には常に2になりますか?

4

4 に答える 4

29

X86 のインクリメント メモリ マシン命令は、 LOCKプレフィックス と共に使用する場合にのみアトミックです。

C および C++ のx++には、アトミックな動作がありません。ロックされていないインクリメントを行う場合、プロセッサが X を読み書きする競合が原因で、2 つの別々のプロセッサがインクリメントを試みた場合、1 つのインクリメントだけ、または両方が表示される可能性があります (2 番目のプロセッサが初期値を読み取ってインクリメントされた可能性があります)。最初の結果が書き戻された後に書き戻されます)。

C++11 はアトミック インクリメントを提供すると私は信じています。また、ほとんどのベンダー コンパイラには、特定の組み込み整数型 (通常は int と long) のアトミック インクリメントを引き起こす慣用的な方法があります。コンパイラのリファレンス マニュアルを参照してください。

「大きな値」(多倍長整数など) をインクリメントする場合は、セマフォなどの標準的なロック メカニズムを使用して行う必要があります。

アトミック読み取りについても心配する必要があることに注意してください。x86 では、32 ビットまたは 64 ビットの値の読み取りは、64 ビット ワードでアライメントされている場合、たまたまアトミックになります。「大きな値」には当てはまりません。ここでも、標準的なロックが必要になります。

于 2012-05-08T17:53:37.747 に答える
8

これは、特定の実装 (gcc) ではアトミックではないという証拠の 1 つです。ご覧のとおり (?)、gcc は次のコードを生成します。

  1. 値をメモリからレジスタにロードします
  2. レジスタの内容をインクリメントします
  3. レジスタをメモリに保存します。

それはアトミックとはほど遠いものです。

$ cat t.c
volatile int a;

void func(void)
{
    a++;
}
[19:51:52 0 ~] $ gcc -O2 -c t.c
[19:51:55 0 ~] $ objdump -d t.o

t.o:     file format elf32-i386


Disassembly of section .text:

00000000 <func>:
   0:   a1 00 00 00 00          mov    0x0,%eax
   5:   83 c0 01                add    $0x1,%eax
   8:   a3 00 00 00 00          mov    %eax,0x0
   d:   c3                      ret

0x0命令のに惑わされないでくださいmov。そこには 4 バイトの余地がaあり、このオブジェクト ファイルがリンクされると、リンカはそこに結果のメモリ アドレスを入力します。

于 2012-05-08T17:57:00.570 に答える
8

誰もあなたの実際の質問に答えていないので、代わりに常に機能する方法でそれを行う方法を示しています:

スレッド 1 は値 0 をロードします

スレッド 2 は値 0 をロードします

スレッド 1 は 1 をインクリメントします

スレッド 2 は値のローカル レジスタ コピーをインクリメントし、1 を格納します。

ご覧のとおり、最終結果は 2 ではなく 1 に等しい値です。最後に常に 2 になるとは限りません。

于 2012-05-08T17:57:15.257 に答える
5

保証されていません。このlock xadd命令を使用して同じ効果を達成したり、 C++を使用したり、 を使用したり、車輪を再発明する手間を省くために作成されたその他の同時実行ソリューションをいくつでも使用したりできますstd::atomic#pragma omp atomic

于 2012-05-08T17:55:15.623 に答える