2012-03-15 18 views
10

アトミックに16バイトの読み書きが必要です。私はcmpxchg16だけを使って書き込みを行います。これは、わかりにくいAMDのものを除いて、すべてのx64プロセッサで利用できます。x64 CPUでのアトミック16バイトの読み取り

ここで問題となるのは、整列した16バイトの値で、cmpxchg16(完全なメモリバリアのように動作する)を使用して変更した場合、16バイトの位置を半分古いデータと半分の新しいデータで読み取ることは可能ですか?

私はSSE命令を読んでいるので(読んでいる途中でスレッドを中断することはできません)、私は読み込みが矛盾したデータを見るのは不可能だと思います。私は原子でなければならないと思う。

私は、cmpxchg16が実行されたときに、16バイトをアトミックに変更し、2つの8バイトブロックを書き込んで、他のスレッドがその間に読み込みを行う可能性はないと仮定しています(正直なところ、原子でなければうまくいく)

私はそうですか?私が間違っている場合、ロックに頼らずに原子16バイトの読み込みを行う方法はありますか?

注:couple similar questions hereがありますが、書き込みがcmpxchg16でのみ行われるケースは扱われないため、これは別個の未解決の質問です。

編集:実際には私の推論は間違っていたと思います。 SSEロード命令は、2つの64ビット読み取りとして実行され、cmpxchg16が別のプロセッサによる2つの読み取りの間で実行される可能性があります。

+1

のような単純なものと評価され、すなわち、それらはアトミックではありません。あなたの書き込みがCMPXCHG16Bで原子的に行われるという違いはありません。読み込みもアトミックでなければならないか、矛盾したデータが表示されることがあります。 AFAIKあなたの唯一の選択はCMPXCHG16Bで読むことです。 – Timo

+0

Yeh、私は読んでいる間にスレッドが中断されるのを止めさせればよいと思ったのですが、実際のバス操作自体はまだインターリーブされている可能性があります。 – Eloff

+0

cmpxchg16bを読み込みで使用すると、読み込み速度が遅くなります。しかし、25%以上のメモリを使用することで、Dmitry Vyukovのハッシュマップのようなseqlockスタイルのアプローチを行うことができます:http://www.1024cores.net/home/downloads – Eloff

答えて

9
typedef struct 
{ 
    unsigned __int128 value; 
} __attribute__ ((aligned (16))) atomic_uint128; 

unsigned __int128 
atomic_read_uint128 (atomic_uint128 *src) 
{ 
    unsigned __int128 result; 
    asm volatile ("xor %%rax, %%rax;" 
       "xor %%rbx, %%rbx;" 
       "xor %%rcx, %%rcx;" 
       "xor %%rdx, %%rdx;" 
       "lock cmpxchg16b %1" : "=A"(result) : "m"(*src) : "rbx", "rcx"); 
    return result; 
} 

これはすべきことです。 typedefは正しい整列を保証します。 cmpxchg16bは、16バイトの境界にデータを整列させる必要があります。

cmpxchg16bは、*srcにゼロが含まれているかどうかをテストし、ゼロの場合はゼロを書き込みます(nop)。いずれの場合も、その後正しい値がRAX:RDXになります。上記

コードは、それはすでに、SSEは、読み込み16バイトは、複数のメモリアクセスを実現できることがリンクされ、質問に答えた

push %rbx 
xor %rax,%rax 
xor %rbx,%rbx 
xor %rcx,%rcx 
xor %rdx,%rdx 
lock cmpxchg16b (%rdi) 
pop %rbx 
retq 
+0

はい、私はこれを行う方法でなければならないと思います。シンプルなSSEロードを2つの64ビットリードに分割し、cmpxchg16がリード間で潜在的に発生する可能性があることが今や私には分かります。 – Eloff

1

参考文献によればhttp://siyobik.info/main/reference/instruction/CMPXCHG8B%2FCMPXCHG16BCMPXCHG16デフォルト原子によってではなく、デフォルトでは、データはリード内で変更及び位相を記述することができることを意味LOCKhttp://siyobik.info/main/reference/instruction/LOCK

を使用することによって、原子することができます。ロックは、読み取りと書き込みの両方をアトミックにします。

+0

"CMPXCHG16Bでは、デスティネーション(メモリ)オペランドが16バイト境界" – kay

+0

申し訳ありません、私はcmpxchg16のロックプレフィックスを意味しました。しかし、ロックはSSE命令では使用できません。 – Eloff

関連する問題