11

2 つのスレッドと共有floatグローバルがあります。1 つのスレッドは変数への書き込みのみを行い、もう 1 つのスレッドは変数からの読み取りのみを行います。この変数へのアクセスをロックする必要がありますか? 言い換えると:

volatile float x;

void reader_thread() {
    while (1) {
        // Grab mutex here?
        float local_x = x;
        // Release mutex?
        do_stuff_with_value(local_x);
    }
}

void writer_thread() {
    while (1) {
        float local_x = get_new_value_from_somewhere();
        // Grab mutex here?
        x = local_x;
        // Release mutex?
    }
}

私の主な関心事は、floatアトミックでないのロードまたはストアが、最終的に偽の部分的に更新された値を持つようになることです。local_xreader_thread

  1. これは正当な懸念事項ですか?
  2. ミューテックスなしで原子性を保証する別の方法はありますか?
  3. sig_atomic_t私の目的に十分なビットがあると仮定すると、共有変数として使用できますか?

問題の言語は、pthreads を使用する C です。

4

7 に答える 7

14

アーキテクチャが異なればルールも異なりますが、一般に、アラインされたintサイズのオブジェクトのメモリのロードとストアはアトミックです。小さくても大きくても問題になる場合があります。したがって、sizeof(float) == sizeof(int)安全かもしれませんが、移植可能なプログラムではまだ依存しません。

また、 の動作はvolatile特に明確に定義されていません... 仕様では、メモリ マップド デバイス I/O へのアクセスを最適化するのを防ぐ方法として使用していますが、他のメモリ アクセスでの動作については何も述べていません。

要するに、ロードとストアが でアトミックであってもfloat xvolatile. ロードとストアがアトミックであるという保証がなければ、メモリ バリアを意味するロックを使用する必要があります。

于 2009-05-13T19:02:37.410 に答える
6

GNU C ライブラリのドキュメントのセクション 24.4.7.2 によると:

int実際には、それ以外の整数型はもはやintアトミックではないと想定できます。ポインター型はアトミックであると想定することもできます。それはとても便利です。これらの前提は両方とも、GNU C ライブラリーがサポートするすべてのマシンと、私たちが知っているすべての POSIX システムに当てはまります。

float技術的には、これらのルールの下ではカウントされませんが、 afloatがアーキテクチャの an と同じサイズである場合int、グローバル変数を anintにし、読み取りまたは書き込みのたびに共用体を使用して float に変換することができます。 .

最も安全な方法は、何らかの形式のミューテックスを使用して共有変数へのアクセスを保護することです。クリティカル セクションは非常に小さいため (単一の変数の読み取り/書き込み)、システムを作成する重いミューテックスとは対照的に、スピン ロックなどの軽量ミューテックスからほぼ確実に優れたパフォーマンスが得られます。その仕事をするように呼びかけます。

于 2009-05-13T19:09:40.580 に答える
3

少なくとも一部のコンパイラでは、割り当てはアトミックではなく、実行するのに1つの命令が必要であるという意味でです。次のコードは、Visual C++6.0によって生成されました。f1とf2のタイプはfloatです。

4:        f2 =  f1;
00401036   mov         eax,dword ptr [ebp-4]
00401039   mov         dword ptr [ebp-8],eax
于 2009-05-13T19:16:02.240 に答える
3

私はそれをロックダウンします。あなたの環境でどのくらいの大きfloatさかはわかりませんが、1 つの命令で読み書きできない可能性があるため、読者は半分書き込まれた値を読み取る可能性があります。volatile操作の原子性については何も述べていないことを覚えておいてください。単に、レジスタなどにキャッシュされるのではなく、メモリから読み取りが行われることを示しているだけです。

于 2009-05-13T18:54:00.763 に答える
1

ミューテックスを使用する必要があると思います。いつの日か、実際の浮動小数点ハードウェアを持たず、代わりにエミュレーションを使用するシステムでコードが実行される可能性があり、その結果、非アトミック float 変数が生成されます。例として、 -msoft-float hereを見てください。

私の答えはあまり役に立ちませんでした。 gcc -msoft-floatおそらく、フロートのロードとストアがアトミックではない特定のケースにすぎません。

于 2009-05-13T19:03:51.213 に答える
0

おそらく、違います。書き込みの衝突の可能性がないので、唯一の懸念は、半分書かれている間にそれを読み取ることができるかどうかです。スレッドを使用して何かを記述している場合、1回の操作でfloatの記述が行われないプラットフォームで、コードが実行される可能性はほとんどありません。

ただし、Cでの浮動小数点の定義では、基盤となるハードウェアストレージをプロセッサのワードサイズに制限する必要がないため、可能です。たとえば、記号と仮数が2つの異なる操作で記述されているマシンコードにコンパイルしている可能性があります。

本当の質問は、「ここにミューテックスがあることの欠点は何ですか?」という2つの質問だと思います。と「ガベージを読み取った場合の影響は何ですか?」

おそらく、ミューテックスではなく、floatのストレージサイズが基盤となるCPUのワードサイズ以下であるかどうかを判断するアサーションを作成する必要があります。

于 2009-05-13T19:16:37.310 に答える
0

メモリ内の単一の単語であるため、変更するのは volatile 宣言だけで問題ありません。

ただし、ロックを使用しない限り、読んだときに最新の値が得られるとは限りません。

于 2009-05-13T18:48:42.660 に答える