MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Charles LeisersonView the complete course: https://ocw.mit.edu/6-172F18YouTube Pl...
00:15:00 このセクションでは、スピーカーは、再帰式と C コードを使用してパスカルの三角形を事前計算する方法について説明します。彼らは、再帰式には choose 関数の呼び出しが含まれていること、および実行時にループを使用してテーブルを事前計算する方法を説明しています。さらに、テーブルの値をソース コードに入れることで、コンパイル時にテーブルを初期化する方法についても説明します。これにより、プログラムの実行時間を節約できます。最後に、プログラムの実行中にアクセスできる最大 10 の二項係数のテーブルの例を示します。
00:20:00 このセクションでは、講演者は、プログラムに定数値の大きなテーブルを手動で入力することを避ける方法として、メタ プログラミングの概念を紹介します。必要なコードを生成するプログラムを作成することで、面倒な作業を自動的に行うことができます。スピーカーは、例として Python コード スニペットを提供します。最近アクセスした結果をキャッシュに保存することで、コストのかかる計算の繰り返しを回避する手法として、キャッシングのトピックも紹介されています。与えられた例は、平方根演算子を使用して直角三角形の斜辺を計算するもので、キャッシュは以前の斜辺を a と b の値とともに事前に保存します。斜辺関数は、最初に入力値がキャッシュ内の値と一致するかどうかをチェックし、一致する場合は、平方根を再計算することなくキャッシュされた値を返します。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Julian ShunView the complete course: https://ocw.mit.edu/6-172F18YouTube Playlist...
00:10:00 このセクションのビデオでは、C でビット単位の演算子を使用して実装できるさまざまな一般的なイディオムについて説明します。1 つの例として、シフトの後に OR または NOT とそして、それぞれ。もう 1 つの例は、ワード X からビット フィールドを抽出することです。これは、目的のビットの位置に 1 を、その他の場所に 0 を使用してマスクを生成し、マスクと X の AND を取り、抽出されたビットを右シフトします。このビデオでは、これらのトリックを使用すると、圧縮またはエンコードされたデータを操作するときに特に役立つことにも言及しています。
00:15:00 このセクションでは、いくつかのビット トリックを使用して、一時変数を使用せずに 2 つの整数を交換する方法について説明します。このコードでは、X を X XOR Y に設定し、次に Y を X XOR Y に設定し、最後に X を X XOR Y に設定します。これは、XOR が独自の逆数であり、最初の行で X のビットが 1 のマスクを生成するためです。と Y が異なります。これは、X とは異なる Y のビットを反転するために使用されます。これにより、一時変数を使用せずにスワップが可能になります。このビデオでは、これらのトリックを使用する際の安全を確保するためのマスキングの重要性も強調しています。
00:30:00 このセクションのビデオでは、プログラミングにおける予測可能および予測不可能な分岐について説明し、予測不可能な分岐の問題に対する解決策として、分岐なしの最小ビット トリックを紹介します。トリックは、「comp」という変数を使用して、a と b の最初の要素の比較結果を格納し、ビット トリックを使用して a と b の最小値を取得することです。次に、最小値を C に置き、「comp」の値に基づいて A または B の値を増減します。このビデオでは、場合によってはこのトリックが機能しない可能性がありますが、コンパイラが何を行っているかを理解することは有益であり、単語のビットハックの多くはベクトルのビットハックとワードハックに拡張できるため、これらのトリックについて知っておくと役立ちます。
00:35:00 このセクションでは、ビデオでビット ハックとプログラミングにおけるその有用性について説明します。与えられた例は、除算を使用せずにより迅速な操作を可能にする剰余加算のちょっとしたトリックです。 Z を X と Y の合計に設定し、それが N より小さいか大きいかをチェックすることにより、プログラムは範囲内にある場合は Z を返すか、Z から N を差し引いた結果を範囲内に戻すことができます。このプログラムは、minimum と同様のロジックを使用しており、分岐の予測ミスを引き起こす可能性のある予測不可能な分岐があります。与えられた別の例は、ビット操作を使用して値を最も近い 2 の累乗に丸める方法です。N をデクリメントし、N を異なる値だけ右にシフトしてビット単位の OR 演算を実行し、最後にインクリメントします。
00:40:00 ビデオのこのセクションでは、スピーカーが 2 つのビット操作の問題について説明します。最初の問題は、与えられた値 n より大きい最小の 2 のべき乗を見つけることです。講演者は、ビット操作を使用してこれを達成する方法を説明し、n が既に 2 のべき乗になっている場合は n をデクリメントして、n の対数から 1 ビットを引いた値が確実に設定されるようにします。 2 番目の問題は、単語 X の最下位のマスクを計算することです。話者は、結果を X に設定し、負の X でビットごとの演算を使用して、これを達成する方法を説明します。話者は、インデックスを見つけるコードも示します。 X を定数で乗算し、結果をテーブルで検索することにより、ビットの値を計算します。セクションは、話者がビット操作を含む数学の手品を実行することで終了します。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Julian ShunView the complete course: https://ocw.mit.edu/6-172F18YouTube Playlist...
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Charles LeisersonView the complete course: https://ocw.mit.edu/6-172F18YouTube Pl...
ビデオのこの部分では、アセンブリ言語に対する C の理解の重要性と、コンパイラを使用してアセンブリ言語で C コードを実装する方法について説明します。特に、LLVM IR が Linux x86 64 呼び出し規約でアセンブリに変換される方法に焦点を当てています。プレゼンターは、LLVM IR の基本コンポーネントと、C プログラミング言語の構造が LLVM IR に変換される方法について説明します。このビデオでは、仮想メモリのレイアウト、複数の関数間での関数呼び出しの調整の問題、Linux x86 64 呼び出し規約での 2 つのポインター (BP と SP) の使用によるすべてのスタック フレームの管理についても取り上げています。
このビデオでは、C to Assembly プログラミングでレジスタの状態を維持するための戦略 (caller-save または callee-save としてレジスタを保存するなど) や、x86 呼び出し規約が無駄な作業を回避する方法についても説明しています。 C およびアセンブリで関数呼び出しがどのように機能するかについて説明し、引数とローカル変数をスタックに保存するプロセス、およびベース ポインターの代わりにスタック ポインターを使用する一般的な最適化について説明します。このビデオでは、LV miR をアセンブリ コードにコンパイルするプロセス、関数のプロローグについて説明するプロセス、レジスタを保存するプロセス、条件を処理するプロセス、および制御フロー グラフを使用して C コードをアセンブリ コードに変換するプロセスも示しています。最後に、結果を返す前にレジスタを復元するために使用される関数エピローグについて説明します。
00:00:00 ビデオのこのセクションでは、TB Shuttle が C をアセンブリ言語に理解することの重要性について説明しています。彼は、アセンブリ言語は C コードよりも精度が高く、C コードからは明らかでないプログラムの詳細を明らかにできることに注目しています。開発者は、アセンブリを確認することで、プログラムの最適化時にコンパイラが何を実行し、何を実行しなかったかを判断できます。さらに、特定のレベルでコードを最適化するときにのみ予期しない動作を引き起こすバグが発生する可能性があり、これらのバグを見つけるのが難しくなります。最後に、アセンブリを理解すると、開発者はアセンブリ コードを手動で変更したり、コードをリバース エンジニアリングしたりできるようになります。
00:05:00 このセクションでは、どのアセンブリ命令を使用するかについて複雑な決定を行う必要があるコンパイラを使用して、アセンブリ言語で C コードを実装する方法、C 条件文とループを実装する方法、および C コードを実装する方法について説明します。関数呼び出しを調整します。変換プロセスを理解するために、ビデオでは LVM IR を紹介しています。これは、コンパイラーがプログラムについて推論するために使用する単純化されたアセンブリーです。ビデオでは、関数、条件、ループなどの C プログラミング言語の構成要素が LVM IR に変換される方法について説明します。このセクションは、LVM IR 属性の簡単な説明で終わります。
00:10:00 このセクションでは、特に Linux x86 64 呼び出し規約で、LLVM ir がアセンブリに変換されるプロセスに焦点を当てています。発表者は、LLVM ir の簡単な入門書を提供し、機能、命令、およびレジスターの基本コンポーネントを説明します。これらは、より単純なバージョンのアセンブリーに似ています。 LLVM ir レジスタは c 変数に似ており、名前で区別され、各関数には独自のローカル レジスタ名があります。プレゼンターは、コード スニペットの例でレジスターを強調し、LLVM のさまざまな基本ブロックを参照するときにレジスターの構文がハイジャックされていることを指摘します。この講演は、フィボナッチ数を計算する単純なコードでこのプロセスがどのように機能するかについてのケース スタディで締めくくられます。
00:15:00 このセクションでは、スピーカーは LV Mir 命令の構文を説明します。これには、レジスタ名、等号、オペコード、およびオペランド リストが含まれます。一部の命令は、ローカル レジスタに格納される値を返しますが、そうでない命令もあります。 LV Mir の命令セットは、x86 の命令セットよりも小さく、データ移動、算術演算、論理演算、および制御フロー用の命令しか含まれていません。 LV Mir では、整数 (ビット数が定義されている)、浮動小数点型、ポインター型、ベクトル型、基本ブロックのラベル型など、すべてが型として公開されます。講演者はまた、LV Mir のベクトル演算は SSE や AVX のようには見えず、ベクトル型で機能する通常の演算に似ているとも述べています。
00:20:00 このセクションのビデオでは、C コードの一連の操作が LLVM IR に変換される方法と、IR でコードを解釈するための経験則について説明します。この抜粋では、LLVM IR が配列や構造体などのプリミティブ型と集約型を処理する方法についても説明し、配列内の要素へのアクセスにメモリ内のアドレスの計算がどのように含まれるかの例を示します。さらに、このビデオでは、C 関数が LLVM IR に変換される方法と、対応する return ステートメントを両方の言語で説明しています。
00:25:00 このセクションでは、C の関数とパラメーターがどのように LV Mir に変換されるかをビデオで説明します。 LV Mir の関数は C の関数に似ていますが、C パラメーターは LV Mir のパラメーターのリストになります。ただし、LV Mir の読み取りは、レジスターの名前が適切でなく、解読が困難であるため、困難な場合があります。このビデオでは、LV Mir の基本ブロックについても説明しています。これは、制御フロー命令に基づいて分割されたコードのチャンクです。基本ブロック間の接続は、分岐命令によって誘導されるエッジに基づいています。最後に、ビデオは LV Mir の条件に触れます。この場合、if-then-else ステートメントは、基本ブロックを誘導し、フロー エッジを制御する条件付き分岐命令になります。
00:35:00 このセクションのビデオでは、ループ本体とループ コントロールを含む C ループのコンポーネントについて説明します。ループ本体は反復ごとに実行され、ループ コントロールはループのすべての反復を管理します。 AC ループは、制御フロー グラフにループ パターンを生成し、LLVM ir にループ構造を作成します。次に、ビデオは、ループ制御の LLVM ir コードを分析します。ここには、ループを処理するときに一般的に発生する奇妙な fie 命令があります。 fie 命令は、コードの LLVM 表現に関する問題を解決しようとします。ここで、私はさまざまなレジスタ全体で表され、実際にどこに行ったのかが不明確になります。
00:45:00 ビデオのこのセクションでは、LLVM IR に焦点を当てています。LLVM IR はアセンブリに似ていますが、すべての計算値が通常の C 変数のようなレジスタに格納されるため、多くの点でより単純です。 LLVM IR は、各変数が最大 1 つの命令によって書き込まれる静的単一代入パラダイムを使用します。このビデオでは、C コードを LLVM IR に変換してからアセンブリに変換する方法について説明していますが、その過程でいくつかの追加の複雑さが伴います。コンパイラは、LLVM IR 操作に必要な実際のアセンブリ命令を選択し、使用する汎用レジスタを決定し、異なるソース ファイルとバイナリ ライブラリ間の関数呼び出しを調整します。次に、Linux x86 64 の呼び出し規約について説明します。
01:05:00 このセクションのビデオでは、C とアセンブリで関数呼び出しがどのように機能するかについて説明します。関数 C を呼び出す前に、関数 B は関数 C の非レジスタ引数を、ローカル変数の下にある独自のスタック メモリ内の予約済みリンケージ ブロックに配置します。負のオフセットでこれらの引数にアクセスします。関数 C が開始されると、関数プロローグが実行されます。関数プロローグは、B のスタック フレームのベース ポインターを保存し、新しいフレームに入るために BP を SP に等しく設定します。次に、独自のローカル変数用にスタック上のスペースを割り当てます。また、B が呼び出し元または呼び出すもののために作成するリンケージ ブロックに使用するスペースも割り当てます。このビデオでは、コンパイラが BP を取り除き、スタック ポインター RSP に基づいてすべてのインデックス付けを実行して、もう 1 つの汎用レジスターを取得する一般的な最適化についても言及しています。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Tao B. SchardlView the complete course: https://ocw.mit.edu/6-172F18YouTube Playl...
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Julian ShunView the complete course: https://ocw.mit.edu/6-172F18YouTube Playlist...
00:25:00 このセクションでは、計算 DAG と、それらを使用してプログラムの並列処理を分析する方法について学習します。計算 DAG は、プログラムのさまざまな部分間の依存関係を表し、スポーン エッジ、呼び出しエッジ、リターン エッジ、継続エッジなど、さまざまな種類のエッジを持ちます。計算データを使用してプログラムの並列度を分析することができ、アムダールの法則を使用して並列度を定量化します。提供されている例では、順次実行する必要があるノードが 7 つ未満であり、計算にある程度の並列性があることを示しています。
00:30:00 このセクションでは、並列処理で可能な最大スピードアップを決定する方法として、アムダールの法則の概念を紹介します。プログラムのシリアル部分は 3/18 であり、最大 6 倍のスピードアップが得られると判断されます。アムダールの法則は並列処理の上限を提供しますが、実際には緩すぎることがよくあります。ワーク法則とスパン法則は、並列処理の別の定義として導入されます。ワーク法則は、P 個のプロセッサでの実行時間が、プログラムの作業を P で割った値以上であることを示し、スパン法則は、実行時間がP 個のプロセッサでの実行時間は、少なくとも無数のプロセッサでの実行時間です。これらの法則は、多くの場合、アムダールの法則よりも優れた最大速度の上限を提供します。
00:45:00 このセクションのビデオでは、並列計算を実行し、観測されたスピードアップを示すプロットを生成した結果と、スパンと仕事の法則からの境界について説明します。プロットは、最大速度向上が約 5 であることを示しており、プログラムの並列処理が低いことを示しています。分析の結果、並列処理のボトルネックはパーティション関数の順次実行であり、クイックソートの並列バージョンの期待される作業とスパンは n log n のオーダーであることが明らかになりました。達成できる最大の並列処理は log log n のオーダーであり、それほど高くはありません。並列処理を増やすには、パーティション関数を並列化する必要があります。
00:50:00 このセクションでは、大幅なスピードアップを実現するために、パーティションおよびマージ ソート アルゴリズムに並列処理を実装することの重要性について講演者が説明します。これらのアルゴリズムの並列バージョンは、全体の範囲が log 二乗 n で制限されており、log n に対する n の高い並列性があります。さらに、高い並列性と、対応する逐次アルゴリズムの作業バウンドと漸近的に等しい作業バウンドを備えた実用的な並列アルゴリズムが他にも多数あります。講演者はまた、スケジューリング理論の概念を紹介し、分散スケジューラが Silk プログラミングで使用される一方で、集中型スケジューラが実行時に計算 DAG を使用可能なプロセッサにマップできることを説明します。例として、計算のすべてのステップで可能な限り多くのことを行う貪欲なスケジューラーを使用します。
00:55:00 このセクションでは、未来を考えずに現在の時間ステップで可能な限り多くの作業を実行する貪欲なスケジューラの概念が紹介されています。少なくとも P 本のストランドが準備できている完全なステップと、P 本未満のストランドが準備できている不完全なステップが定義されます。 1968 年に Ron Graham によって最初に示された有名な定理は、貪欲なスケジューラによって達成される時間境界は、T1/P + T 無限大以下であると述べています。T1 は作業であり、T 無限大はスパンです。この定理の証明が提供され、任意の貪欲なスケジューラーが最適な実行時間の 2 倍以内で達成されることが示されています。
01:00:00 このセクションでは、最適スケジューラの 2 分の 1 以内で達成する貪欲なスケジューラ バウンドの帰結をビデオで説明します。 T1/Tinfinity が P^2 以上の場合、欲張ったスケジューラーはほぼ完全な線形スピードアップを達成するという結果が得られます。ここで、T1/P に T infinity を掛けると、プロセッサの数と比較した計算の並列処理の量が測定されます。利用可能。シルク スケジューラはワーク スチール スケジューラを使用します。これは、T1/P に次数 T 無限大を加えたものに等しい TP の予想実行時間を持ち、スケジューリングのオーバーヘッドを考慮して T 無限大の前に Big O を置き、ほぼプロセッサの数が T1/Tinfinity よりもはるかに少ない限り、完全な線形速度アップです。シルク ランタイム システムは、準備が整ったストランドのワーク デックを維持することで機能し、デックの下部をスタックのように操作します。 Silk Scale の計測機能により、作業とスパンの項を測定して、プログラムの並列性を判断できます。
01:05:00 このセクションでは、スピーカーはプロセッサのスポーンと並列処理の概念について説明します。彼らは、プロセッサが関数を呼び出すと、その関数のフレームをスタックの一番下に配置し、スタックの一番下にフレームを生成できると説明しています。複数のプロセスが並行して発生する可能性があり、スポーンと呼び出しからリターンを行うことができます。労働者がやるべき仕事がなくなると、彼らは別のプロセッサのデッキの一番上から盗みます。有名な定理によると、ワーカーが盗む頻度は非常に低く、線形に近いスピードアップが得られます。また、スピーカーは、Silk がポインタに関する C の規則をサポートしていることにも注意します。この規則では、スタック スペースへのポインタを親から子に渡すことができますが、子から親には渡すことができません。
01:10:00 ビデオのこのセクションでは、スピーカーは Cactus スタックについて説明します。これは、Silk プログラムの祖先計算グラフ内のタスクによって表示されるスタックです。このスタックを使用すると、スタックの複数のビューを並列に表示できるため、並列関数呼び出しが可能になります。講演者は、Silk プログラムに必要なスタック スペースは、プログラムのシリアル実行に必要なスタック スペース (S sub 1) に、使用されるプロセッサの数 (P) を掛けることで求めることができると説明しています (Sサブ P ≤ P x S サブ 1)。スピーカーは、この概念の高レベルの証明を提供し、P プロセッサの実行に必要なスタック スペースの上限は、多くの場合、実際に必要な量よりもはるかに緩いことに注意します。仕事を盗む時間。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Julian ShunView the complete course: https://ocw.mit.edu/6-172F18YouTube Playlist...
このビデオでは、分割統治の繰り返しを分析するためのマスター メソッドについて説明し、n の対数基数 B と A の対数基数 B を比較して、n の成長と必要な作業を決定することにより、マルチスレッド アルゴリズムに適用します。このビデオでは、基本的なマルチスレッド アルゴリズムのソリューションを含むチート シートを紹介し、作業とスパンの分析、作業効率、粒度最適化による間接費の克服などのトピックを取り上げます。技術的な話題を伝える際の共感の重要性が強調され、DAG の概念が作業とスパンのバランスをとって並列処理を増やし、実行時間を短縮する手段として導入されます。
00:00:00 このセクションでは、インストラクターは、生徒に分割統治の繰り返しと、それらを解決するためのマスター メソッドと呼ばれる一般的な方法について思い出させることから始めます。このメソッドは、繰り返しとその形式 T(n) = a*T(n/B) + F(n) を扱います。ここで、a は定数、B は分割係数、F(n) は総作業量です。問題をサイズ n/B の部分問題に分割します。生徒は、再帰ツリーと、各レベルがサイズ n/B のサブ問題にどのように分割されるかを思い出します。行全体の実行時間を加算し、ツリーの高さを計算して、各レベルのサブ問題の数を掛けます (a ^k)。最後に、学生は A の n^log ベース B がアルゴリズムの合計実行時間であることを計算します。
00:05:00 このセクションでは、マルチスレッド アルゴリズムを評価する際に n の増加と必要な作業を決定する方法についてスピーカーが説明します。重要なのは、n の対数底 B と、N の F を持つ A の対数底 B を比較することです。話者は 3 つの考えられるケースを取り上げます。最初の例は、対数底 B n が n の F よりもはるかに大きい場合です。この場合、重みの定数部分は葉にあり、A の対数底 B に対する答えは n になります。2 番目のケースは、対数底 B n が n の F にほぼ等しい場合です。このために、追加の対数を追加すると、答えは対数底 B に対する n から k に n の 1 を加えたものになります。最後に、3 番目のケースは、対数ベース B が N の F よりもはるかに小さい場合です。これは、F が規則性条件を満たす必要があることを意味します。これは、多項式や対数など、対象となるすべての関数によって満たされます。
00:35:00 このセクションでは、技術的なトピックに関するコミュニケーションにおける共感の重要性が強調されています。教授は、授業の内容に慣れていない可能性のあるクラスの他の生徒に対しても、忍耐強くあるよう学生に勧めます。マルチスレッド アルゴリズムの分析に移ると、ベクトル加算の分割統治アルゴリズムが提示され、並列処理は log n に対して n であることがわかります。並列処理とプロセッサ数の関係が議論されており、教授は、並列処理が多いほど良く見えるかもしれませんが、それは特定のしきい値までしか有益ではないことを強調しています。
00:40:00 このセクションでは、スピーカーは、マルチスレッド アルゴリズムのオーバーヘッドの一部、特にサブルーチン呼び出しのオーバーヘッドを最適化する方法について説明します。それらは「粒度」の概念を導入し、分割統治プロセスのリーフでチャンクあたり最大 G 個の要素があることをコンパイラーに示唆します。これにより、サブルーチンのオーバーヘッドを 1 回だけではなく G 回の反復で償却できるため、パフォーマンスが向上します。粒度が指定されていない場合、システムはオーバーヘッドを最小限に抑えるために最善の推測を行います。スピーカーは、変数 I、G、および s を分解して、このコンテキストでの作業を分析し、並列制御要素のない元のコードでの作業と比較します。
00:50:00 このセクションでは、スピーカーはマルチスレッド アルゴリズムの分析、特に DAG (有向非巡回グラフ) の概念と、それがアルゴリズムのパスに与える影響について説明します。それらは、並列処理を可能にするために、DAG の異なるサブツリー間の独立性の必要性を強調しています。目標は、アルゴリズムの作業と範囲のバランスを取ることです。これら 2 つの要因は反対方向に作用するからです。重要なのは、G (並列処理の量) を I (アルゴリズムの順次部分) よりもはるかに大きくすることです。これにより、オーバーヘッドが小さくなり、処理が高速になります。講演者は、この概念の実装についても言及していますが、これについては講義シリーズで後述することに注意してください。
00:55:00 このセクションでは、スピーカーは for ループを使用して 2 つのベクトルを追加するマルチスレッド アルゴリズムの実装を提示します。ループは V add と呼ばれる演算子を使用してシリアル ベクトル加算を実行し、ループはサイズ G のベクトルを使用して G のグループで加算を生成します。G が 1 に等しいと仮定すると、ループの作業は次数 n であり、スパンも注文n。並列処理は、作業とスパンの比率をとることによって測定されます。これは、n を n で割ると 1 に単純化されます。スピーカーは、マルチスレッド アルゴリズムを分析する目的は、並列処理を増やし、スパンを減らしてランタイムを最小限に抑えることであることを強調し、手法を強調します。これはストリップ マイニングと呼ばれ、マルチスレッド アルゴリズムを改善する 1 つの方法として、長さ N のループを二重のネストされたループに置き換えて計算を並列化します。
01:05:00 このセクションでは、スピーカーはマルチスレッド アルゴリズムでの分割統治戦略の使用について説明し、いくつかのタスクにチャンクされていない限り、多数の小さなタスクを次々に生成しないようアドバイスします。結構です。一般に、スレッドに与えられるタスクの数が十分に多い場合、分割統治アプローチが必要です。講演者は、スケジューリングのオーバーヘッドに注意するよう警告し、より多くのオーバーヘッドがある内側のループではなく、外側のループを並列化することを提案しています。ここに示すコード例は、スケジューリングが 1 回だけ発生する効率的なコードと、オーバーヘッドが n 回発生する厄介なコードを示しています。行列の乗算は、分割統治法を使用するマルチスレッド アルゴリズムの例として使用され、n を n 行列で乗算するために、n を 2 行列で n を 2 行列で 8 回乗算し、次に 2 つの n x n 行列を加算します。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Charles LeisersonView the complete course: https://ocw.mit.edu/6-172F18YouTube Pl...
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Tao B. SchardlView the complete course: https://ocw.mit.edu/6-172F18YouTube Playl...
00:40:00 このセクションでは、スピーカーはソフトウェア パフォーマンスを測定するためのさまざまなツールと方法について説明します。これには、time コマンドを使用して外部からプログラムを測定すること、clock get time またはその他の方法を使用してタイミング呼び出しをプログラムに入れること、gdb を使用してプログラムを中断することが含まれます。 perf ツールセットで使用されるようなハードウェアと OS のサポートを活用するか、プログラムをシミュレートして、より遅い速度でより深い理解を得るために、どのルーチンが最も時間がかかっているかを特定します。講演者は、time コマンドを使用した場合の経過時間、ユーザー時間、およびシステム時間の違いと、プロセッサの割り当てにより合計時間がどのように加算されないかについて説明します。
00:45:00 このセクションでは、スピーカーは、ウォール クロック時間、ユーザー モードで費やされたプロセッサ時間、カーネルで費やされた時間など、さまざまな種類のタイミングと測定について説明します。使用が推奨されるタイミング コールは、決して逆方向に実行されないことを保証する clock monotonic オプションを使用した clock get time です。実行には非決定的な時間がかかる場合がありますが、異なるコアで異なる応答を返し、逆方向に実行される可能性がある RTIDTSC などの他のタイマーよりも信頼性が高くなります。スピーカーは、get time of day を使用しないように警告します。
00:50:00 このセクションでは、スピーカーは、clock_gettime の使用や time コマンドでの測定など、プログラミングでイベントを測定および時間計測するさまざまな方法について説明します。彼らは、時間の経過とともに技術が変化する可能性があり、エンジニアが適応する必要があるかもしれないと警告しています.講演者はまた、単純なプロファイリング手法としてランダムな瞬間にコードを中断することを提案し、Facebook などの大企業がこの方法を使用していると述べています。さらに、スピーカーは、ハードウェア カウンターとライブラリ livepFM4 のアイデアを紹介します。これにより、プロセスごとにこれらのカウンターにアクセスできます。彼らは、技術者が常に外科的に正確なツールを必要とするわけではなく、単純なツールで十分な場合があることを強調しています.
01:05:00 このセクションでは、平均を含むさまざまなタイプの要約統計について説明します。これは、さまざまなコンテキストでのパフォーマンスの有用な尺度を提供できます。 Web サーバーを評価する場合、CPU 使用率と合計タスク完了時間は算術平均を使用して測定できますが、実時間とパーセンタイル動作は、要求の満足度を最適化するためにより関連する場合があります。ただし、プログラム A と B のパフォーマンスを比較するなど、比率を要約する場合、算術平均を取ることは有効な方法ではありません。これは、ビデオに示されている例に示されているように、比率の平均が比率自体と同じではないためです。
MIT 6.172 Performance Engineering of Software Systems, Fall 2018Instructor: Charles LeisersonView the complete course: https://ocw.mit.edu/6-172F18YouTube Pl...
MIT 6.172 ソフトウェア システムのパフォーマンス エンジニアリング、2018 年秋 - 1. 導入と行列乗算
1. 導入と行列乗算
「1. Introduction and Matrix Multiplication」というタイトルのこの YouTube ビデオでは、講師がパフォーマンス エンジニアリングの重要性と、それがどのように進化してきたかについて説明しています。行列乗算の例を使用して、講演者は、コーディング手法とマシン仕様がパフォーマンスにどのように大きく影響するかを示します。ディスカッションでは、ループの順序、キャッシュの使用、並列プログラミングなどのトピックが取り上げられています。講演者は、さまざまなプロセッサや算術計算用にコードを最適化する方法についても説明します。全体として、このビデオは、パフォーマンス エンジニアリングの世界と、現代のコンピューティング システムにおけるその実用的なアプリケーションに関する貴重な洞察を提供します。
講義 2. 仕事を最適化するための Bentley ルール
2. 仕事を最適化するための Bentley ルール
この YouTube ビデオでは、コンピューター プログラムのさまざまな最適化手法について説明しています。作業を最適化するための Bentley ルールが導入され、最適化はデータ構造、ループ、ロジック、および関数にグループ化されます。値のエンコード、データ構造の拡張、事前計算、キャッシング、スパース行列の利用など、さまざまな手法について説明します。講演者は、グラフィックス プログラムでグラフ、ロジックの最適化、衝突検出の最適化に疎行列表現を使用する利点についても触れています。これらの最適化手法を実装すると、プログラムの実行時間が短縮され、プログラムがより効率的になります。
ビデオの 2 番目の部分では、ループの巻き上げ、ループでのセンチネルの使用、ループの展開と融合、関数のインライン化など、いくつかのカテゴリの最適化手法について説明します。講演者は、時期尚早の最適化を避けるようアドバイスし、正確さを維持し、回帰テストを使用することの重要性を強調します。このビデオでは、生産性を向上させ、効率的な方法で目標を達成するための 6 ステップのガイドである、仕事を最適化するための Bentley ルールについても概説しています。これらのルールには、明確な目標の設定、タスクの分割、計画と整理、タスクの優先順位付け、気を散らすものを最小限に抑える、定期的なアプローチの見直しと調整が含まれます。
講義3.ビットハック
3.ビットハック
この YouTube ビデオでは、バイナリ表現、2 の補数、ビットごとの演算子、一時変数を使用しない変数の交換、コードの最適化など、さまざまなビット操作のトピックを取り上げています。このビデオでは、if-else ステートメントを使用せずに 2 つの整数の最小値を見つける方法や、一時変数を使用せずに 2 つの整数を交換する方法など、さまざまなちょっとしたトリックを紹介しています。講演者は、予測不可能な分岐について説明し、予測可能な分岐が利用できない場合に備えて分岐なしの最小ビット トリックを紹介し、除算などのコストのかかる演算を単純なビット単位の演算に置き換えることで、ビット ハックがコードを最適化する方法を示します。このビデオでは、de Bruijn 列と、N クイーン問題などの問題を解く際のその応用についても説明しています。
第 2 部では、ビット ベクトルを使用して N クイーン問題を解き、バイナリ ワード内の 1 ビットの数を効率的にカウントする方法について説明します。バックトラッキングを使用して N クイーン問題を実装し、ビット ベクトルを使用してボードを効率的に表現します。 N クィーン問題でクィーンを安全に配置するための 3 つのチェックについて説明し、最下位の 1 ビットを再帰的に削除して、単語内の 1 ビットの数をカウントする方法を示します。さらに、1 のビット数をカウントするためのテーブル ルックアップとレジスタ操作の使用についても説明します。ビデオは、語長の底 2 の対数に比例する性能を持つ 1 ビットをカウントするための分割統治アプローチのデモンストレーションで終了します。さらに学習するためのリソースも提供されています。
講義 4. アセンブリ言語とコンピュータ アーキテクチャ
講義 4. アセンブリ言語とコンピュータ アーキテクチャ
このビデオでは、アセンブリ言語とコンピューター アーキテクチャの包括的な概要を説明します。アセンブリ言語は、コードのパフォーマンスを最適化するための重要なインターフェイスであり、アセンブリ言語を習得するにはコンピューター アーキテクチャを理解することが不可欠です。講演者は、x86 64 アーキテクチャとその開発の歴史、主要なレジスタ、データ型、メモリ アドレッシング モード、命令セット アーキテクチャ (スタック、整数論理とバイナリ論理、ブール論理、サブルーチンを含む) について説明します。また、ゼロ拡張や符号拡張などの拡張機能や、アセンブリ言語のさまざまなアドレッシング モードについても説明しています。さらに、このビデオでは、浮動小数点型、ベクトル、ベクトル ユニット、従来の命令と SSE 命令、およびスーパースカラー処理、アウト オブ オーダー実行、分岐予測などのコンピューター アーキテクチャ設計機能について説明します。
このビデオでは、アセンブリ言語とコンピューター アーキテクチャに関連するいくつかのトピックも取り上げています。中心的なテーマの 1 つは、命令レベルの並列処理 (ILP) とパイプラインのストールです。これらは、データの依存関係などの危険によって引き起こされます。講演者は、真、逆、および出力データの依存関係と、スーパースカラー プロセッサがハードウェアでより多くの並列処理を利用して一度に複数の命令を実行する方法について説明します。ただし、危険を回避するために、アーキテクトは、分岐の結果を推測して事前に実行する投機的実行だけでなく、名前の変更や並べ替えなどの戦略を実装しています。スピーカーは、ソフトウェアの最適化をよりよく理解するために、聴衆にこれらの方法を理解するよう促します。
講義 5. C からアセンブリへ
講義 5. C からアセンブリへ
ビデオのこの部分では、アセンブリ言語に対する C の理解の重要性と、コンパイラを使用してアセンブリ言語で C コードを実装する方法について説明します。特に、LLVM IR が Linux x86 64 呼び出し規約でアセンブリに変換される方法に焦点を当てています。プレゼンターは、LLVM IR の基本コンポーネントと、C プログラミング言語の構造が LLVM IR に変換される方法について説明します。このビデオでは、仮想メモリのレイアウト、複数の関数間での関数呼び出しの調整の問題、Linux x86 64 呼び出し規約での 2 つのポインター (BP と SP) の使用によるすべてのスタック フレームの管理についても取り上げています。
このビデオでは、C to Assembly プログラミングでレジスタの状態を維持するための戦略 (caller-save または callee-save としてレジスタを保存するなど) や、x86 呼び出し規約が無駄な作業を回避する方法についても説明しています。 C およびアセンブリで関数呼び出しがどのように機能するかについて説明し、引数とローカル変数をスタックに保存するプロセス、およびベース ポインターの代わりにスタック ポインターを使用する一般的な最適化について説明します。このビデオでは、LV miR をアセンブリ コードにコンパイルするプロセス、関数のプロローグについて説明するプロセス、レジスタを保存するプロセス、条件を処理するプロセス、および制御フロー グラフを使用して C コードをアセンブリ コードに変換するプロセスも示しています。最後に、結果を返す前にレジスタを復元するために使用される関数エピローグについて説明します。
レジスタ、呼び出し規約では、各関数が使用できるレジスタのルールと、関数呼び出しを通じてそれらのレジスタを保持する方法について詳しく説明しています。
講義 6. マルチコアプログラミング
講義 6. マルチコアプログラミング
このビデオ講義では、マルチコア プログラミングと、ムーアの法則によるマルチコア プロセッサの出現とクロック周波数のスケーリングの終焉について説明します。講演者は、プロセッサが直面する電力密度の問題と、それがムーアの法則に追いつくためにチップに複数のコアを追加することにつながった方法について説明します。この講義では、共有メモリ ハードウェアのキャッシュ コヒーレンス プロトコルの基本と、並列プログラミングの抽象化を提供する Pthreads、TBB、OpenMP、Silk などの同時実行プラットフォームについても説明します。各プラットフォームの長所と短所について説明し、フィボナッチ プログラムの実装例を示します。このビデオでは、マルチコア プログラミングの包括的な概要と、プログラマーが直面する課題と解決策について説明します。
このビデオでは、並列処理を処理するための抽象化ツールである Silk のさまざまな側面についても説明します。講演者は、ネストされたシルク for ループ、アセンブリ コードの生成、レデューサーを使用したリダクション、スケジューラー、パフォーマンスの最適化などのトピックについて説明します。また、Silk エコシステムの概要と、それぞれデバッグとスケーラビリティの分析のための Silk Sanitizer や Silk Scale などの関連ツールも提供します。主なポイントは、マルチコア プロセッサ用の並列プログラムを作成するのは困難な場合があるということですが、Silk は複雑なタスクを効率的に処理することでプロセスを簡素化し、プログラマーがコードの実行をより細かく制御できるようにします。
講義 7. レースと並列処理
講義 7. レースと並列処理
このビデオでは、Silk プログラミングのレース、並列処理、および計算タスクに関連するさまざまなトピックを取り上げます。カバーされるいくつかの重要な概念には、同時実行のための spawn ステートメントと sync ステートメント、競合状態を回避することの重要性、それらを識別するための Silk の競合検出器の使用が含まれます。このビデオでは、プログラム内の並列処理の量を定量化する方法として、アムダールの法則、仕事の法則、スパンの法則、および計算の作業とスパンを分析する方法についても説明します。貪欲なスケジューラの定理に焦点を当てて、並列ソート アルゴリズムの潜在的な高速化と並列性、およびスケジューリング理論の概念についても説明します。全体として、このビデオは、Silk プログラミングでのプログラム パフォーマンスの理解と最適化に関する貴重な洞察を提供します。
このビデオでは、貪欲なスケジューラ バウンドの結果が説明されています。これは、基本的に、T1/Tinfinity が P^2 以上である限り、貪欲なスケジューラがほぼ完全な線形スピードアップを達成することを示しています。ワーク スティーリング スケジューラを使用するシルク スケジューラは、プロセッサの数が T1/Tinfinity よりもはるかに少ない限り、ほぼ完全な線形速度向上を実現できます。シルク ランタイム システムは、準備が整ったストランドのワーク デックを維持することで機能し、デックの下部をスタックのように操作します。ビデオでは、Cactus Stack についても説明しています。これにより、スタックの複数のビューを並行して使用でき、並行関数呼び出しが可能になります。 P プロセッサの実行に必要なスタック領域の上限は、多くの場合、実際に必要な量よりもはるかに緩いです。これは、各プロセッサが作業を盗むたびに計算グラフをずっと下る必要がない場合があるためです。
講義 8. マルチスレッドアルゴリズムの分析
講義 8. マルチスレッドアルゴリズムの分析
このビデオでは、分割統治の繰り返しを分析するためのマスター メソッドについて説明し、n の対数基数 B と A の対数基数 B を比較して、n の成長と必要な作業を決定することにより、マルチスレッド アルゴリズムに適用します。このビデオでは、基本的なマルチスレッド アルゴリズムのソリューションを含むチート シートを紹介し、作業とスパンの分析、作業効率、粒度最適化による間接費の克服などのトピックを取り上げます。技術的な話題を伝える際の共感の重要性が強調され、DAG の概念が作業とスパンのバランスをとって並列処理を増やし、実行時間を短縮する手段として導入されます。
このビデオでは、ワークとスパンに焦点を当てたマルチスレッド アルゴリズムの分析、およびスパンを最小化しながら並列処理を最大化して、ほぼ完全な線形スピードアップを達成する方法についても説明します。講演者は、スレッドに与えられるタスクの数が十分に大きいマルチスレッド アルゴリズムへの分割統治アプローチを提案し、スケジューリング オーバーヘッドが原因で多数の小さなタスクを生成しないように警告します。提示されたコード例には、効率的なものと粗末なものが含まれています。スピーカーは、2 次元コーディングとインデックス付けで部分行列を表現する方法についても説明し、パフォーマンスを向上させるために分割統治型行列乗算コードで「restrict」を使用することを強調します。
講義 9. コンパイラにできることとできないこと
講義 9. コンパイラにできることとできないこと
このビデオでは、さまざまな例を使用して、コンパイラがコードを最適化する方法について説明します。コンパイラが不要なストレージとメモリの参照を削除する方法と、ループを最適化してパフォーマンスを向上させる方法について説明します。
このビデオでは、コンパイラー最適化パスの概念と、それらを使用してコードのパフォーマンスを向上させる方法についても説明しています。また、特にベクトル化に関して、コンパイラーの制限についても説明します。コンパイラーは、コード内のポインターが別名にならないと判断できる場合にのみ、コードをベクトル化できます。ポインターが別名である場合、コンパイラーはコードをベクトル化できません。プログラマーは、ポインターに注釈を付けてその使用法に関する詳細情報を提供することで、コンパイラーを支援できます。
講義 10. 測定とタイミング
講義 10. 測定とタイミング
このビデオでは、スピーカーは、精度に影響を与える可能性のある外部要因を含め、コンピューティングにおける測定とタイミングのさまざまな側面について説明します。モデルの必要性とデータの明確な理解を強調し、差異を減らして誤差を補正し、適切なタイミング コールを使用して信頼性を確保します。また、パフォーマンス モデリング、タイミング コール、ハードウェア カウンター、シミュレーターなどのツールを強調しながら、べき乗則や非決定論的要因など、ソフトウェア パフォーマンスを正確に測定する際の課題についても説明します。最後に、彼らは単一のツールに依存しないように警告し、正確な結果を保証するための手法として三角測量と適応を推奨しています。
講演者は、パフォーマンス ソフトウェア エンジニアリングにおける信頼性の高いパフォーマンス測定の重要性について説明します。彼は、パフォーマンスを正確に測定するために統計を使用することを推奨し、さまざまなコンテキストでパフォーマンスの有用な尺度を提供できる、平均などのさまざまな種類の要約統計について説明しています。彼は、比率の算術平均を取ることは有効なアプローチではないと指摘し、代わりに幾何平均を使用することを提案しています。スピーカーは、プログラムを比較するときにデータを集計する正しい方法を選択することの重要性を強調し、パフォーマンスをより正確に比較するために、複数の実行から最小または 10% などの低次の統計を取得することを提案します。スピーカーは、直接比較や統計を導出するためのモデルのフィッティングなど、パフォーマンスの測定と比較のためのさまざまな方法論についても説明しますが、モデリングにおけるオーバーフィッティングの問題について警告します。全体として、このビデオは、プログラムのパフォーマンスを改善するための信頼できるパフォーマンス測定の重要性を強調しています。