2017-09-21 18 views
0

変数にアトミックまたは非アトミックにアクセスすることがあります。C11変数へのアトミックおよび非アトミックなアクセスを混在させる

int var = 0; 
var++; 
atomic_fetch_add(&var, 1); 

しかし、これが打ち鳴らす4.0.1でコンパイルされません:

error: address argument to atomic operation must be a pointer to _Atomic type ('int *' invalid) 
atomic_fetch_add(&var, 1); 

私は見つけることができる最善の解決策はキャストである:私はgccの上のあなたのような何かを書くことができることにconvinient見つける理由であります

int var = 0; 
(*(int*)&var)++; 
atomic_fetch_add(&var, 1); 

これを達成するためのより簡単でポータブルな方法はありますか?

+0

"これはclangでコンパイルされません" ---エラーメッセージが参考になります。 – zerkms

+0

Btw、それをやることの本来の目的は何ですか?最初の値の変更は他のスレッドでは保証されないので、 'var ++;'の値は効果的に適用されません。 – zerkms

+1

これはどのように*できますか? '_Atomic int'と' int'は異なる型なので、それらへのポインタは自動的に変換されません。手動でキャストすると、オブジェクトの有効な型ではなく(文字型ではない)左辺式を使用してオブジェクトへのアクセスに対して未定義の動作が発生します。 – EOF

答えて

0

C標準で定義された抽象マシンは、ほとんどの実際のマシンとはかなり異なるストレージビューを持っています。特に、メモリアクセスを、必要な状況に応じてさまざまな方法で実行できるアクションとして考えるのではなく、各オブジェクトが1種類の読み取りと最大で1種類の書き込みをサポートしていることを表示します(const - 修飾オブジェクトどんな種類の書き込みもサポートしていません)。オブジェクトにアクセスするために必要な読み書きの種類は、その型によって異なります。

このようなアプローチは、いくつかの種類のハードウェアプラットフォームやいくつかの最適化戦略には役立つかもしれませんが、実際のプラットフォーム上で動作する多くの種類のプログラムにはあまり適していません。残念なことに、Standardは、プログラマが特定のオブジェクトをほとんどの場合「通常の」ストレージとして扱うべきだが、プログラム実行中の特定の特定の時間に、より正確なメモリセマンティクスが必要であることを認識できる実用的な方法を認識していません。

2

C11には、制限の少ないアトミックオブジェクトを操作できる2つのインターフェイスがあります。

最初に、アトミックオブジェクトを常に上書きすることができます。アトミックオブジェクトにアクセスする唯一のオブジェクトであることがわかっている場合は、通常初期化フェーズでatomic_initを使用します。

第2に、いくつかのスレッドでも実行中のアクセスに対する保証が必要ない場合は、制限の少ないアクセスモードを使用できます。つまり、atomic_fetch_and_add_explicit(&var, 1, memory_order_relaxed)などできます。これにより、あなたのアクセスが個であることが保証されます(アトミックから必要とするプロパティの1つ)が保証されますが、別のスレッドが更新された値を参照することを保証するものではありません。

しかし、一般的に言えば、アトミックアクセスがパフォーマンスに重大な影響を及ぼす場合、あなたは何か間違ったことをしています。したがって、アトミックでの意味のあるやり取りを試みる前に、コードをベンチマークして、実際にボトルネックかどうかを確認してください。もしそうなら、まずアルゴリズムを変更する方法を考えてください。たとえば、レースの対象とならないローカル変数の計算を増やしてください。それらのすべてがあなたに必要なパフォーマンスを与えることができない場合にのみ、C11が提供するさまざまなメモリセマンティクスを調べてください。

関連する問題