CompareExchangeに基づくインターロックされた実装はSpinWaitを使用する必要がありますか?


8

以下は、に基づくインターロックされたメソッドの実装ですInterlocked.CompareExchange

このコードでSpinWait繰り返しを行う前にスピンを使用することをお勧めしますか?

public static bool AddIfLessThan(ref int location, int value, int comparison)
{
    int currentValue;
    do
    {
        currentValue = location; // Read the current value
        if (currentValue >= comparison) return false; // If "less than comparison" is NOT satisfied, return false
    }
    // Set to currentValue+value, iff still on currentValue; reiterate if not assigned
    while (Interlocked.CompareExchange(ref location, currentValue + value, currentValue) != currentValue);
    return true; // Assigned, so return true
}

私はSpinWaitこのシナリオで使用されているのを見てきましたが、私の理論では、それは不必要なはずです。結局のところ、ループには少数の命令しか含まれておらず、常に1つのスレッドが進行しています。

このメソッドを実行するために2つのスレッドが競合していて、最初のスレッドはすぐに成功するが、2番目のスレッドは最初は何も変更を行わず、繰り返す必要があるとします。他の候補がない場合、2番目のスレッドが2回目の試行で失敗することはまったく可能ですか?

例の2番目のスレッドが2回目の試行で失敗しない場合、SpinWait?で何が得られるでしょうか。メソッドを実行するために100のスレッドが競合しているというまれなイベントで、数サイクルを削ぎ落としますか?


3
@MindSwipe OPは、Interlockedを使用する必要があるかどうかを尋ねていません。むしろ、彼は空のループ本体の代わりにSpinWaitを使用する必要がありますか?
マシューワトソン

1
SpinOnceシングルスレッドのOSが枯渇するのを防ぐためだけに使用する必要があるでしょう。stackoverflow.com/questions/37799381/…を
マシューワトソン

1
@MindSwipeを使用することにより、競合状態はすでに正しく処理されていInterlockedます。明確にするために、私はCPUサイクルSpinWait意味のある形で節約したり、(@ MatthewWatsonに感謝)シングルスレッドOSが不足したりしないようにするなど、が意味があるかどうかにのみ関心があります。
Timo

1
@AloisKraus理論的には理解していますが待機するかどうかに関係なくこのループは次の試行で成功するというのが私の推論です。SpinWaitとにかく同じ数の試行が実行されるので、それは私がそれが電力消費を減らすことさえないと期待する理由です!(2つのスレッドがある場合、これは最初のスレッドで1回、2番目のスレッドで2回の試行です。)
Timo

1
@ Timo、Interlockedがハードウェアでサポートされていないがエミュレートする必要があるプラットフォームでは、スピンロックのメリットがあると思います。
Nick

回答:


2

私の専門家ではない意見では、この特定のケースでは、2つのスレッドが時々を呼び出すためAddIfLessThan、a SpinWaitは不要です。2つのスレッドが両方ともAddIfLessThanタイトなループで呼び出している場合は、各スレッドが中断せずに数マイクロ秒間進行できるようにすると便利です。

実際に私は実験を行い、AddIfLessThanタイトなループで呼び出す1つのスレッドと2つのスレッドのパフォーマンスを測定しました。同じ数のループを(累積的に)作成するには、2つのスレッドで約4倍の時間が必要です。SpinWaitミックスにa を追加すると、2つのスレッドは単一のスレッドよりもわずかに遅くなります。


1
SpinWaitは1つのスレッドに対してどのような影響がありますか?たとえば、それを使用しない理由はありますか?
Ian Ringrose

2
@IanRingroseは15%遅くなります。メソッドSpinWait内で型の変数を宣言します。AddIfLessThanそれは値型であり、そのSpinOnceメソッドが呼び出されることはありませんが、それでもオーバーヘッドが追加されます。
Theodor Zoulias

3
@TheodorZoulias:IL本体でローカルの初期化をスキップするように宣言できます。これにより、パフォーマンスがほぼ回復します。言語サポートがまだないため、このためのILコードを発行する必要があります。github.com/dotnet/csharplang/blob/master/proposals/…を参照してください。スピンしたい場合は、Resetを呼び出してからSpinOnceを呼び出します。
Alois Kraus

1
@TheodorZouliasに感謝します。ちなみに、2つのスレッドは私のポイントを説明するための例にすぎません。これはクラスライブラリであり、消費者が適切と考えるときに使用できます。私たちにできる最善のことは、多くのスレッドによる競合状態の可能性について仮定を行うことです。操作にかかる時間がほとんどないことを考えると、多くのスレッドがこの操作を互いにオーバーラップして実行する可能性は低いと思います。
Timo

1
タイトなループを更新する場合は、値をプライベートにして、ループの終わりに一度更新することを検討する必要があります。共有される値を多かれ少なかれ実際に保つ必要があり、ループが非常に長い場合は、Xミリ秒ごとに1回、進行状況バーを進めるように値を更新することを検討してください。
curiousguy

2

2つのスレッドについては、SpinWait議論の対象にはなりません。しかし、このコードは、リソースを実際に争うことができるスレッドの数を知らせず、比較的多くのスレッドを使用するSpinWaitことで、有益になる可能性があります。特に、スレッドの数が多いと、リソースを正常に取得しようとしているスレッドの仮想キューが長くなり、たまたま最終的にサービスが提供されるこれらのスレッドは、スケジューラによって割り当てられたタイムスライスを超える可能性が高くなり、より高いCPU消費につながり、優先度が高くても、他のスケジュールされたスレッドの実行に影響を与える可能性があります。のSpinWait許可されたスピンの上限を設定することにより、この状況に適切な回答が得られます。その後、コンテキストの切り替えが実行されます。したがって、コンテキストの切り替えをトリガーするために高価なシステムコールを行う必要性と、特定の状況で他のスレッドの実行に影響を与えるリスクのある制御されていないユーザーモードのCPU消費との間の妥当なトレードオフです。


2つのスレッドは、私のポイントを説明するための例にすぎません。これはクラスライブラリです。その可能性を考慮に入れて、現実的なシナリオに対処できるはずです。操作にかかる時間がほとんどないことを考えると、多くのスレッドがこの操作を互いにオーバーラップして実行する可能性は低いと思います。
Timo

あなたは公正な主張をします。スレッドが多い場合、一部のスレッドは成功する前に多くのスレッドで失敗することに同意します。しかし、私には、操作が非常に小さいため、たとえば100回実行してもまだピーナッツだと思う人もいます。これを念頭に置いて、あなたはそれがSpinWaitやり過ぎになることを期待しますか?
Timo

2
@Timo、唯一の答えは測定です。これが、私が想定しているさまざまな負荷およびハードウェアシナリオに対処できるライブラリコードになることを特に考慮します。公平性を向上させ、スループットを向上SpinWaitさせるには、高負荷のシナリオの可能性を事前に除外しない限り、それを使用しない場合よりも(数十マイクロ秒の比較的小さなコストで)優れた戦略を使用して、スループットが可能な負荷ポイントを見つける影響を受けると、それが必要かどうかにかかわらず、ヒントが表示されます(コアの数にも依存する場合があることに注意してください)。
Dmytro Mukalov

非常に頻繁に共通リソースを必要とする多くのスレッドで、頻繁にタイムスライスを消費する可能性があるため、リソースのプライベートコピーを作成するか(後で同期される)、スレッドを破棄することも検討します。
curiousguy '11 / 11/19

@curiousguy 4つのコメントで述べたように、これはクラスライブラリです。もちろん、使用するコードはケース固有のアプローチを使用できます。ただし、クラスライブラリのポイントは、さまざまなユースケースに対応できるようにすることです。だからこそ、SpinWait付加価値のある状況に疑問が残ります。これまでのところ、それらは、シングルコアの場合、および(B)(A)のように見える可能性が非常に高い競合ケース。
Timo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.