問題タブ [micro-architecture]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
x86 - スタック バッファを返しますか?
私が理解したように、Return Stack Buffer は 4 ~ 16 のエントリのみをサポートし (wiki から: http://en.wikipedia.org/wiki/Branch_predictor#Prediction_of_function_returns )、キーと値のペアではありません (ret 命令の位置によるインデックス付けに基づく) )。本当ですか?コンテキスト スイッチが発生すると、RSB はどうなりますか?
リターン スタック バッファ長が 16 の CPU で返されない関数が 50 個あるとします。その後はどうなりますか? すべての予測が失敗するということですか?あなたはそれを説明できますか?このシナリオは、再帰関数呼び出しでも同じですか?
c - メモリ依存の推測により、BN_consttime_swap が定数時間になることはありませんか?
環境
OpenSSLの機能 BN_consttime_swap
は美しいものです。このスニペットでは、またはcondition
として計算されています。0
(BN_ULONG)-1
高レベルの bignum 操作に一定の時間がかかるようにするために、この関数は 2 つの bignum を交換するか、一定の時間内にそのままにしておくことが意図されています。それらをそのままにしておくと、実際に各 bignum の各単語を読み取り、古い単語と同一の新しい単語を計算し、その結果を元の場所に書き戻します。
これには、bignum が効果的に交換された場合と同じ時間がかかることが意図されています。
この質問では、Agner Fog が最適化マニュアルで説明しているような最新の広範なアーキテクチャを想定しています。C コードからアセンブリへの直接的な変換 (C コンパイラーがプログラマーの努力を台無しにすることなく) も想定されています。
質問
上記の構成が「ベスト エフォート」型の一定時間実行として特徴付けられるのか、それとも完全な一定時間実行として特徴付けられるのかを理解しようとしています。
a
特に、関数が呼び出されたときに bignum がすでに L1 データ キャッシュにあり、BN_consttime_swap
関数が返された直後のコードがすぐに bignum で作業を開始するというシナリオが懸念されa
ます。最新のプロセッサでは、bignuma
が使用されたときにコピーが技術的に終了しないように、同時に十分な数の命令を実行できます。BN_consttime_swap
への呼び出しの後の命令が動作するようにするメカニズムa
は、メモリ依存スペキュレーションです。議論のために単純なメモリ依存の推測を仮定しましょう。
質問が要約すると、これは次のとおりです。
BN_consttime_swap
メモリから読み取られた後、投機に反して関数内に書き込まれたコードをプロセッサが最終的に検出した場合、プロセッサはアドレスが書き込まれたことを検出するとすぐに投機的実行をキャンセルしますか、それともそれ自体を許可しますか?書き込まれた値が既に存在していた値と同じであることを検出したときにそれを保持するには?
最初のケースでは、BN_consttime_swap
完全な定数時間を実装しているように見えます。2 番目のケースでは、ベストエフォートの定数時間のみです。bignum がスワップされていない場合、への呼び出しの後に来るコードの実行は、スワップBN_consttime_swap
されている場合よりもかなり高速になります。
2 番目のケースでも、これは、2 つの bignum のそれぞれの単語ごとに、2 つの可能な final とは異なる値を書き込むことによって、近い将来 (プロセッサが十分に素朴である限り) 修正できるように見えるものです。古い値または新しい値を再度書き込む前に値を変更します。通常のvolatile
コンパイラがシーケンスを過度に最適化するのを防ぐために、ある時点で型修飾子を含める必要があるかもしれませんが、それでも可能に思えます。
注:ストア転送については知っていますが、ストア転送はショートカットにすぎません。後に来るはずの書き込みの前に読み取りが実行されることを防ぎません。そして、状況によっては失敗しますが、この場合は期待できません。
caching - (NVIDIA) GPU L1 キャッシュ ラインが L2 キャッシュ ラインよりも長いのはなぜですか?
NVIDIA Fermi および Kepler GPU (おそらく Maxwell も) では、L1 キャッシュ ラインの長さは 128 バイトですが、L2 キャッシュ ラインの長さは 32 バイトです。それは逆であってはいけませんか?つまり、L1 ははるかに小さいので、スラッシングを防ぐためにメモリの短いセグメントをキャッシュしようとするべきではありませんか?
x86 - MOVDQU で実装されたコピー ループによって示される実行ごとの大きな分散
x86 movdqu 命令 (movdqu 命令は、xmm- との間の 16 バイト データの移動をサポートします) を使用して、あるソース メモリ ロケーションからある宛先メモリ ロケーションに反復ごとに 64 バイトを移動するループで見られる結果の説明を求めています。整列されていないメモリ位置との間のレジスタ)。これは、memcpy()/java.lang.System.arraycopy() に似た関数を実装するコードの一部です。
コピーを実装しようとした 2 つの異なるパターンがあります。
パターン1
このパターンでは、rsi はソース (src) アドレスを保持し、rdi は宛先 (dst) アドレスを保持し、xmm レジスターは一時レジスターとして使用されます。このコードは、copylen_in_bytes/64 回繰り返されます。ご覧のとおり、ここでは ld-ld-st-st-ld-ld-st-st ロード-ストア パターンに従います。
パターン2
pattern2 では、ld-st-ld-st-ld-st-ld-st パターンに従います。
観察
このコードを数百回実行すると、src と dst がさまざまな 8 バイト境界で整列され、次のことがわかります。
Westmere の場合 (Xeon X5690)
パターン 1 は、実行ごとに非常に高い分散を示します。
パターン 2 はほとんど分散を示しません。
パターン 2 の最小時間 (観測された最速時間) は、パターン 1 の最小時間よりも (~8%) 長くなります。
Ivybridge で (Xean E5-2697 v2)
パターン 1 は、実行ごとに非常に高い分散を示します。
パターン 2 はほとんど分散を示しません。
パターン 2 の最小時間は、パターン 1 の最小時間よりも高くなっています (~20%)。
ハスウェル (Core i7-4770)
パターン 1 は、非常に高い実行ごとの分散を示しません。
パターン 2 はほとんど分散を示しません。
パターン 2 の最小時間は、パターン 1 の最小時間よりも高くなっています (~20%)。
奇妙なことに、Westmere と Ivybridge では、src/dest のアラインメントと悪い結果 (高い分散の原因) との間に相関関係がないようです。同じ src/dest アラインメントに対して良い数値と悪い数値が表示されます。
質問
キャッシュラインにまたがる movdqu のパフォーマンスが、キャッシュラインにまたがらない movdqu よりも悪いことは理解していますが、次のことはわかりません。
1) パターン 1 が Westmere と Ivybridge で高い分散を示すのはなぜですか? ロードストアの順序はどのように違いますか?
2) 異なるアーキテクチャ間で、パターン 2 の最小時間がパターン 1 よりも遅いのはなぜですか?
この長い投稿をお読みいただきありがとうございます。
カーシック
cpu - データ転送を登録するためのキャッシュラインはどのように機能しますか?
int
10 個の要素の配列があるとします。64 バイトのキャッシュラインでは、 から までの 16 個の配列要素を保持できarr[0]
ますarr[15]
。
arr[5]
たとえば、 L1 キャッシュからレジスターにフェッチするとどうなるか知りたいです。この操作はどのように行われますか? CPU はオフセットをキャッシュラインに取り込んで次のn
バイトを読み取ることができますか?
node.js - 画像アップロード要求を別のサーバーに転送する
いわゆる「マイクロアーキテクチャ」(基本的に、完全に独立して実行できるが同時に連携できる複数の小さな NodeJS プロジェクト) に基づいて NodeJS REST API プロジェクトを構築しようとしています。
現在、ユーザーはアプリから画像をアップロードでき、NodeJS バックエンドが画像を適切に処理して保存します。
今、私がやりたいことは次のとおりです。
ユーザーがアプリからアップロードする画像を選択 -> アプリが「メイン API」エンドポイントにリクエストを送信 -> メイン API エンドポイントがこのリクエストを「イメージ サービス」に転送 -> イメージ サービス (これは完全に別のサーバー) が正常に終了した場合、画像が保存されている URL をメイン API サーバー エンドポイントに返す必要があり、メイン API サーバー エンドポイントはアプリに情報を返します。
私の質問は、画像のアップロード要求をあるサーバーから別のサーバーに転送するにはどうすればよいですか? 理想的には、メイン API がイメージを一時的に保存してから、イメージ サービスにリクエストを送信することは望ましくありません。
私が望むのは、メイン API が受信したデータを Image Service サーバーに直接転送することです。ディスクやメモリに一時的に保存することなく、ある場所から別の場所にデータを「ストリーミング」したいと言うことができると思います。文字通り、あるサーバーから別のサーバーに「トンネル」したいだけです。
これは可能ですか、これは効率的な方法ですか? アプリがアクセスする 1 つの中心点が必要なだけで、この Image Service サーバーについて知られたくありません。アプリがメイン API に対してのみリクエストを行い、必要に応じて他の小さなサービスを呼び出すようにしたいと考えています。
NodeJS、Express、Multer (画像のアップロード用)、および Digital Ocean ホスティング (それによって違いが生じる場合) を使用しています。
c++ - wait() 関数は何をしますか?
こんにちは、私は Java の学習を開始し、現在 C++ を学習しようとしています。私はこのコードを持っていますが、それが何をするかを理解できません。プログラムが開始する前に、プログラムを一定時間待機させると想定しています。しかし、いくつかのさらなる説明は非常に役に立ちます。
さらに説明が必要なセクションにコメントを追加しました。