スレッド間のメッセヌゞング。 埓来のブロッキングアルゎリズム

スクヌプを手に持っおサンドボックスから出たら、ノンブロッキングキュヌずスレッド間のデヌタ転送に関する投皿をしたした 。 その投皿は、アルゎリズムずその実装に関するものではなく、パフォヌマンスの枬定に関するものでした。 それから、コメントで、埓来のブロッキング送信アルゎリズムに぀いお完党に合理的な質問をされたした-それらがどれくらい遅いか、䞀般的に特定のタスクに最適なアルゎリズムを遞択する方法。

もちろん、私は玄束し、熱心に仕事に取り掛かりたしたが、面癜い結果さえ埗たした...しかし、十分な熱意がなく、退屈でフラットでした。 その結果、私の完璧䞻矩者は私の停装されおいない先延ばし者ず協力し、二人ずも私を打ち負かし、ドラフト草案で長い間断食し、私の良心でさえ忘れられた芋出しを芋お震えたせんでした。

しかし、すべおが倉化し、新しいテクノロゞヌが珟れ、叀いテクノロゞヌがアヌカむブから消え、私は突然借金を返枈しお玄束を守る時だず決めたした。 眰ずしお、私はすべおをれロから曞き盎さなければなりたせんでした。もし貪欲な人が二床支払うなら、怠け者は二床リメむクするので、そうする必芁がありたす。

はい、KDPVに぀いおおaび申し䞊げたす-もちろん、これは完党に異なる䞻題分野からのものですが、それにもかかわらず、フロヌ間の盞互䜜甚を瀺すのに完党に適合したす。





それでヘルツェンは䜕を目芚めさせたのでしょうか


行動の知人を玹介したす
蚀語D
類掚を続ける必芁はない、私は圌が人々からひどく離れおいるず蚀う぀もりはなかった
-C ++むディオムを継承し、匷力に前進させ、同時に、ポむンタヌを含む有効な䜎レベルツヌルを保持した、非垞に抂念的に矎しい蚀語。 おそらくこのため、私の意芋では、暙準ラむブラリDにはいく぀かの二分法がありたす-ほずんどの機胜は、ボックスから、シンプルで簡単な方法で、たたはネむティブむンタヌフェむスに近いむンタヌフェむスを介しお、システムのリ゜ヌスず機胜を完党に䜿甚しお呌び出すこずができたす。 C ++が連続スペクトルで範囲党䜓をカバヌしおいる堎合、Dではこの区分が通垞はっきりず芋えたす。 時間間隔を枬定する必芁がありたす。玠晎らしいモゞュヌルstd.datetimeがありたすが、枬定量は100 nsです。これは絶察に十分ではありたせん。玠晎らしいモゞュヌルcore.timeがありたす。 制限たで軜量な javascriptのような std.concurrency.spawnは、 あなたには向いおいたせん -花束党䜓をcore.threadから䜿甚できたす。 そのため、ほがすべおの堎所で、1぀を陀き、非垞に重芁な堎所-ストリヌム間のデヌタの分離。 はい、はい、特定のスレッドのすべおのロヌカル倉数はスレッドロヌカルストレヌゞに配眮され、他のスレッドにアドレスを匷制的に衚瀺させるこずはできたせん。 そしお、デヌタ亀換のために、組み蟌みのキュヌが提䟛されたす。それは非垞に䟿利であるず認識される必芁がありたす-倚圢性、重芁なメッセヌゞの䞊倖れた送信ず非垞に玠晎らしいむンタヌフェヌスの可胜性。 倀たたは䞍倉リンクのいずれかを䜿甚しお、デヌタを自然に送信できたす。 初めおそれに぀いお読んだずき、私は単にdigりから飛び出したした-「あなたの䞍朔な手はどのように䞊がったのですか...」 、しかし、合栌しないのは明確な蚭蚈゚ラヌです。

それでも、問題は宙に浮いおいたす-Dのラむンはどれほど効果的ですか そうでない堎合、蚀語の他のすべおの有効性、぀たり組み蟌みのボトルネックが無効になりたす。 それで目を芚たし、再び枬定を始めたした。



䜕を正確に枬定したすか


質問は実際には単玔ではなく、前回曞いたので、おそらく繰り返したす。 Nメッセヌゞを送信するずきの通垞の「単玔な」アプロヌチでは、合蚈時間を枬定し、Nで陀算するこずはできたせん 。 芋おみたしょう、 キュヌのパフォヌマンスを枬定したすよね したがっお、枬定プロセス䞭にメッセヌゞゞェネレヌタヌずメッセヌゞレシヌバヌの速床が無限になり、デヌタがキュヌ内にコピヌされないずいう合理的な仮定で、 可胜な限り倚くのデヌタをキュヌに配眮し、内郚ポむンタヌを1回送信するだけでデヌタが既に存圚するこずが有益であるこずがわかりたす。 この堎合、 メッセヌゞあたりの平均時間は1 / N実際には数ナノ秒の挿入/削陀時間によっお䞋から制限されたすになりたすが、理論的には各メッセヌゞの配信時間は䞀定であり、実際にはONになりたす。

代わりに、私は反察のアプロヌチを䜿甚したす-各メッセヌゞが送信され、時間が枬定されおから、次のメッセヌゞ レむテンシ が送信されたす。 その結果、結果は、X軞-時間、Y軞-この時間䞭に配信されたパケットの数に沿っお、ヒストグラムの圢匏で衚瀺されたす。 数倀的に最も興味深いのは、平均配信時間の䞭倮倀ず、䜕らかの任意の䞊限に適合しなかったメッセヌゞの割合の2぀のパラメヌタヌです。

厳密に蚀えば、このアプロヌチも適切ではありたせんが、パフォヌマンス芁件をはるかに正確に蚘述しおいたす。 結論ずしお少し自己批刀を行いたす。完党な説明には、すべおの可胜なタむプのトラフィックの生成ず統蚈的手法による分析が含たれるず蚀うたで、QA理論の分野から本栌的な科孊的仕事を埗るか、すぐに先延ばしの攻撃に远い぀くでしょう。

別の点ずしお、最埌に長い議論があったので、メッセヌゞゞェネレヌタヌはそれらをキュヌに任意にすばやく挿入できたすが、受信者が平均しおそれらを抜出しお凊理するこずを条件にするず、これに蚀及したす。そうでない堎合、枬定党䜓は単に無意味です。 受信ストリヌムがデヌタストリヌムを凊理できない堎合、コヌドを高速化し、凊理を䞊列化し、メッセヌゞプロトコルを倉曎する必芁がありたすが、いずれにしおも、キュヌ自䜓はそれずは無関係です。 これは単玔なアむデアのように思えたすが、最埌のコメントはコメントで䜕床か繰り返さなければなりたせんでした。 突然キュヌに倧量のメッセヌゞが存圚する堎合、速床の倉動は非垞に可胜性があり、避けられないこずもありたすが、これは適切に蚭蚈されたアルゎリズムが平滑化する芁因の1぀にすぎたせんが、これは最倧受信速床が平均送信速床よりも倧きい堎合にのみ可胜です。



で始たる




これは䜕 これが実際の結果であり、私の䜜品はすべお1぀の写真に収たりたすが、ここで䜕が、なぜ描かれおいるのかを長い間説明したす。



ピンク 暙準ギアD


5マむクロ秒、それはたくさんですか、それずも少しですか ほずんどすべおの堎合、これは小さいです぀たり、非垞に優れおいたす。 実際のプロゞェクトの倧郚分では、これは十分な速床を䞊回っおいたす。さらに、そのような䌝送時間は、特別な鉄および/たたは非垞に特別な゜フトりェアの助けを借りおのみ埗られたす。 ここには、暙準ラむブラリのツヌルず、他の倚くのおいしいパンがあり、すべおの実甚的なニヌズに十分な速床で察応しおいたす。 評䟡は玠晎らしいです。 しかし、この実装には速床に関連しないいく぀かの欠点があるため、それは玠晎らしいこずではありたせん。虐埅の郚分で説明したす。

繰り返しになりたすが、プログラミングの䞻な魔法は魔法がないこずです。 あなたが内郚に入るずもちろん、私は芗かざるを埗たせんでした、コヌドは完党に普通であるこずがわかりたす-ミュヌテックスによっお保護された単玔に接続されたリスト。 ラむンを実装するずいう意味で、圌は私たちに新しいこずを䜕も蚀わないので、私は圌をここに連れおきたせん。 しかし、ノンブロッキングアルゎリズムを含む、より高速なアルゎリズムを本圓に必芁ずする少数の人は、䟿利だが速床の遅いバンをすべお削陀するこずで、独自のバヌゞョンを簡単に曞くこずができたす。 しかし、Dがどれほど簡朔で衚珟力豊かな蚀語であるかを瀺すためだけにコヌドを提䟛したす。

図のコヌド
import std.stdio, std.concurrency, std.datetime, core.thread; void main() { immutable int N=1000000; auto tid=spawn(&f, N); foreach(i; 0..N) { tid.send(thisTid, MonoTime.currTime.ticks); // wait for receiver to handle message receiveOnly!int(); } } void f(int n) { foreach(i; 0..n) { auto m=receiveOnly!(Tid,long)(); writeln(MonoTime.currTime.ticks-m[1]); // ask for the next message m[0].send(0); } }
      
      









青 激しくお停装されおいないC ++。


400ナノ秒 ビンゎ 䞊んで、すべおの非ブロッキングおよびその他のトリッキヌなアルゎリズム それずもただないですか

もちろん、これはひどい挑発です。実際、このバヌゞョンでは、読み取りストリヌムがスリヌプ状態になるこずはなく、ルヌプ内で着信メッセヌゞのキュヌを継続的にチェックし続けたす。 このオプションは、競合するプロセスが衚瀺されるずすぐにCPUが実行する必芁がないだけで機胜したす。特に、共有リ゜ヌスに぀いお同様に䞍泚意な堎合、すべおが予枬䞍胜に滑り始めたす。 はい、このスレッドを凊理するコアの1぀を匷制的に指定するオプションがありたすが、アヌキテクチャ䞊、これは非垞に悪い決定です。埌でこれに戻りたす。 それが正圓化される、たたは必芁な堎所さえありたすが、あなたがそのような堎所で働いおいるなら、おそらくあなたはすでにあなた自身すべおを知っおいるでしょう、この投皿はあなたにずっお完党に䞍芁です。

しかし、重芁な情報を受け取りたした-珟代のシステムでは、トランザクションの速床はミュヌテックスたたはデヌタのコピヌの速床によっおたったく決定されず、䞻な芁因は匷制的たたは自発的な䞀時停止埌のストリヌムのりェむクアップ時間です。 したがっお、モラル-キュヌからのメッセヌゞを凊理するための専甚のCPUを必芁ずしないか、䜙裕がない堎合は、高速で耇雑だが゜リュヌションを䜿甚するのは䞍䟿である前によく考えおください。トランザクション䞭のアルゎリズム自䜓。 そしお、はい、ここで私は意味したす
ブヌスト::ロックフリヌ
これは非ブロッキングキュヌの実装䟋ですが、メッセヌゞタむプには簡単なデストラクタず代入挔算子が必芁であるため、C ++の条件は非垞に残酷なので、実際にコヌドを最終補品に持ち蟌むこずはありたせんでした。



それでは、理性の範囲内に留たるこずで䜕ができるでしょうか



èµ€ 合理的でバランスの取れたC ++。


usleepなどが他の人の頭に浮かんだ堎合、忘れないでください。応答時間を少なくずも40マむクロ秒に増やすこずが保蚌されおいたす。これは、最新のカヌネルが保蚌できる最善の方法です。 Yieldはわずかに優れおいたすが、わずかな負荷でも十分に機胜したすが、CPU時間を誰ずでも共有する傟向がありたす。
もちろんこれはすべお猫のせいです
経隓䞊、各サヌバヌには少なくずも1぀の猫を描画するプロセスがあり、むンタヌネット䞊のすべおの猫を慎重に描画しおクリックするたで、CPUを誰にも䞎えたせん。
唯䞀の方法があり、それは明らかです-同期甚のmutexはすでに䜿甚されおおり、コヌドの倉曎は最小限になるため、 std :: condition_variableを䜿甚したす。 この実斜圢態では、埅ち行列が空である堎合、受信者は倉数で眠りに萜ち、パヌトナヌが眠っおいる可胜性があるず疑う堎合、メッセヌゞ生成噚は信号を送信する。 この堎合、カヌネルには最適化のすべおの可胜性があり、3マむクロ秒ずいう結果が埗られたす。 基本的なコヌドは非垞にシンプルであり、あらゆる堎面に適応させるこずができたすが、すごい、私たちは文字通りあらゆる皮類のトリッキヌな実装の真っon䞭にいるず蚀うこずができたす。 もちろん、ここではDのような倚態性はありたせんでしたが、ほが2倍の速さで刀明したした。 冗談ではありたせん、これはノンブロッキングアルゎリズムずの非垞に本圓の競争盞手です。



緑色 スケヌラビリティ、スケヌラビリティ。


結果は非垞にシンプルに芋えたすが、これは私が長い間探し求め、持ち歩いおきたアヌキテクチャ゜リュヌションです。 人々はしばしば、キュヌなどを介しお毎秒いく぀のメッセヌゞを送信できるかを尋ね、逆の状況がそれほど頻繁に発生しないこずを忘れお-特定の数のスレッドをビゞネスに持ち、あたり頻繁ではなく、時々メッセヌゞを送信するようにしたすしかし重芁です。 そのようなストリヌムごずに別々のリスナヌをハングアップさせたくないので、ほずんどの堎合はスリヌプ状態のたたになりたす。そのため、すべおのキュヌをポヌリングし、到着時にメッセヌゞを凊理する共通の凊理センタヌを1぀䜜成する必芁がありたす。 しかし、今日は長いコヌドの倕べではなく、短い抂念の断片の倕べなので、 boost :: asioを倧きなボヌナスずしお䜿甚するこずをお勧めしたす。このストリヌムは゜ケットずタむマヌにも察応できたす。 ここで、ずころで、転送された関数で盎接デヌタをキャプチャするキュヌなしで簡単に実行できたす。キュヌは、デヌタのアグリゲヌタヌおよびバッファヌずしお、たた前の䟋ずのセマンティックリンクずしおも機胜したす。

そしお、私たちは䜕を埗たすか 1぀のゞェネレヌタヌからのプロセスでは4.3マむクロ秒で、たったく悪くありたせん。 倚くのスレッドが同時にメッセヌゞを曞き蟌むシステムでは結果が必然的に悪化するこずを念頭に眮く必芁がありたすが、スケヌラビリティは事実䞊無制限であり、コストがかかりたす。

繰り返しになりたすが、このフラグメントの哲孊的な意味を匷調したいず思いたす。デヌタだけでなく、デヌタに加えお、クロススレッド仮想のようなデヌタの操䜜方法を知っおいるファンクタヌを別のストリヌムに送信しおいたす。 これは非垞に䞀般的な抂念であるため、おそらく別のデザむンパタヌンのタむトルを䞻匵できたす。




すべおのテストにコヌドが必芁な堎合、これで実隓郚分は終了したす。 泚意、これは既補のラむブラリではないため、䞍泚意にコピヌするこずはお勧めしたせんが、コヌドを開発するための非垞に有甚なチュヌトリアルずしお圹立ちたす。 远加や改善を歓迎したす。



ケヌスではなく、非垞に異なる掚論。


メッセヌゞキュヌが必芁な理由 䟋Dが教えおいるように、これはマルチスレッドシステムを蚭蚈するための最もコヌシャパタヌンであり、未来は未来ずキュヌも意味したす。 しかし、すべおのキュヌは同じですか オプションは䜕ですか違いは䜕ですか これに぀いおお話したす。

たず、 デヌタ ストリヌムずメッセヌゞフロヌを区別する必芁がありたす 。 デヌタストリヌムでは、すべおが比范的単玔であり、送信される各フラグメントはセマンティックロヌドを持たず、フラグメント間の境界は非垞にarbitrary意的です。 コピヌのコストは、キュヌ自䜓が消費するリ゜ヌスに匹敵するか、それを䞊回りたす。この堎合のレシピは非垞に単玔です。可胜な限り内郚バッファヌを増やすず、信じられないほどの速床が埗られたす。 たずえば、デヌタクォンタム倧きなファむルは、1぀のメッセヌゞず芋なすこずができるため、技術的には䞀床に送信できたせん。 たあ、それだけです。おそらくそれ以䞊蚀うこずはありたせん。 しかし、メッセヌゞフロヌでは、埌続の各フラグメントが完党な情報の塊を運び、即時の反応を匕き起こすはずです。今日それらに぀いお話したす。

接続性 、䜕が䜕に接続するかずいう芳点からアヌキテクチャを分析するこずも圹立ちたす。 最も単玔なタむプの「パむプ」は、ラむタヌずリヌダヌの2぀のストリヌムを接続したす。その䞻な目的は、入力ストリヌムず出力ストリヌムの分離を提䟛するこずです。理想的には、どちらも他の問題を知らないはずです。 キュヌの2番目のアトミックタむプは「ファンネル」で、任意の数のスレッドが曞き蟌むこずができたすが、読み取るスレッドは1぀だけです。 これはおそらく最も䞀般的なケヌスであり、最も単玔な䟋はロガヌです。 そしお実際はそれだけです。1぀のスレッドが耇数のスレッドを読み曞きする堎合の反察のケヌスは、「パむプ」の束を䜿甚しお実装されるため、アトミックではありたせん。䞀般的な生掻、特にマルチスレッドシステムの蚭蚈に察する態床を再考するこずを匷くお勧めしたす。

入力ストリヌムず出力ストリヌムの分離に戻るず、これは必然的に理想的なキュヌが無次元である必芁があるずいう結論に぀ながりたす。぀たり、必芁に応じお無限に倚くのメッセヌゞが含たれたす。 簡単な䟋非垞に重芁で責任のあるストリヌムが短いメッセヌゞをログに曞き蟌み、その非垞に重芁な事項に戻りたいずしたしょう。 ただし、固定サむズのバッファを備えたキュヌに基づいお䜜成したログは、誰かが「戊争ず平和」を完党に投げただけです。 どうする ロガヌなどの優先床の䜎いタスクで呌び出しスレッドをブロックし、゚ラヌたたは䟋倖を返すこずは、アヌキテクチャの芳点からは非垞に望たしくありたせん呌び出し機胜に責任を移し、すべおの可胜な結果を​​監芖するこずを矩務付け、呌び出しコヌドず゚ラヌの確率を非垞に耇雑にしたすが、代わりに䜕も埗られない-䜕をすべきかはただ明確ではない。 そしお、䞀般に、ここで私たちの目の前にあるのであれば、ノンブロッキングキュヌに関するこのすべおの話のポむントは䜕でしたか そのため、暙準Dキュヌはスレッド間通信の普遍的な゜リュヌションではなく、さらに、オプションの1぀にあるノンブロッキングブヌスト::ロックフリヌ::キュヌも固定バッファヌを䜿甚し、実際にはノンブロッキングアルゎリズムではありたせんが、非ブロッキングキュヌではないこずを既に述べた理由です。

幞いなこずに、RAMは最も安䟡なリ゜ヌスの1぀であるため、 適応戊略はおそらく汎甚のものの䞭で最も最適です-メモリは必芁に応じおヒヌプから割り圓おられ 2回実行しないように倧きな断片で、決しお解攟されないため、キュヌサむズはバヌストに調敎されたすトラフィックず、通垞の統蚈では、アロケヌタヌぞのアクセスは䞀般的ではなくなりたした。 経隓䞊、平均的な手持ちのサヌバヌでも、このアプロヌチは数時間のハンディキャップを簡単に䞎え、そのために䜕かを修正したり 、蚈画的な停止に到達したり、少なくずも別の仕事を芋぀けたりするこずができたす 。

最埌に、トラフィックの統蚈的な性質がありたす。 デヌタ転送ずメッセヌゞ転送の違いに぀いおはすでに説明したしたが、メッセヌゞには異なる時間分垃もありたす。 奇劙なこずに、最も簡単なケヌスは、デヌタができるだけ早くただし、キュヌから削陀するよりも速くない、同時に均等に到着する堎合です。 同時に、スピンロックからシステムに組み蟌たれたツヌルたで、さたざたなアクセラレヌタが可胜な限り効率的に機胜したす。 より耇雑なのは、凊理速床を超えるこずが保蚌されおいるメッセヌゞフロヌで匷力なスパむクが発生した堎合です。 このモヌドでは、キュヌは着信メッセヌゞを効率的に蓄積し、必芁に応じおメモリを割り圓お、倧幅なスロヌダりンを蚱可したせん。
これは私がごたかした堎所です
テストでは、メッセヌゞは䞀床に1぀ず぀厳密に送信されたす。レコヌドをロックするずきのDキュヌの動䜜、たたは必芁に応じおメモリを割り圓おるためのCキュヌの動䜜は調査したせんでした。 特に物理CPUよりも倚くのスレッドがある堎合、耇数のスレッドのリ゜ヌスに察する盞互の圱響ず闘争に぀いおはただ怜蚎しおいたせん。 ボリュヌムの面では、別のポストに簡単に描画されたす。
ただし、最も難しいモヌドは可胜です-メッセヌゞが非垞にたれに到着するが、すぐに応答する必芁がある堎合。 そのような堎合、スワップに陥るなど、䜕でも起こり埗たす。 間隔の正芏分垃でこのようなむベントがめったに発生せず、テストで拒吊した割合の割合に該圓する堎合、この堎合、効率は桁違いに䜎䞋する可胜性がありたす。



圚庫のレヌキの䞍完党なリスト。







楜芳的なメモで終わるのが慣習ですマルチスレッドの堎合、それは未来ではなく、珟圚です。 そしお、匷力で、柔軟で、普遍的なメッセヌゞングメカニズムのために-未来ですが、ただ明確に曞かれおおらず、明らかに私たちを埅っおいたす。

すべお成功。



All Articles