1

WindowsとLinuxのスレッド(またはファイバー)について、任意のプログラミング言語で一般的な質問があります。

「2番目のスレッドを待機」させて、すぐに実行に移し、プリエンプトされることなく、数ミリ秒の間小さなタスクを支援することは可能ですか?ミューテックスとスピンロックのない読みやすいコードを望んでいることを付け加えておきます。

従来のスレッドプールが小さなタスクでは機能しないことを示すために、C#でのマトリックス反転の問題を検討してください。IvanKuckirの行列クラスを使用しています。彼のInvert関数をコピーして、次のようにInvertParallelと呼びます。

public Matrix InvertParallel()   // modified from Ivan's Invert(), see link above
{
    if (L == null) MakeLU();
    Matrix inv = new Matrix(rows, cols);
    Parallel.ForEach<int>(Enumerable.Range(0, rows), rowID =>
    {
        Matrix Ei = Matrix.ZeroMatrix(rows, 1);
        Ei[rowID, 0] = 1;
        Matrix col = SolveWith(Ei);
        inv.SetCol(col, rowID);
    });
    return inv;
}

次に、Invert関数とInvert_Parallel関数の両方を呼び出して、それにかかる時間を測定します。

static void Main()
{
    Stopwatch sw = new Stopwatch(); sw.Start();
    Matrix A = Matrix.IdentityMatrix(50, 50);
    Matrix I1 = A.Invert();
    long elapsed1 = sw.ElapsedMilliseconds;
    Matrix I2 = A.InvertParallel();
    long elapsed2 = sw.ElapsedMilliseconds - elapsed1;
    Console.WriteLine("Matrix size=" + A.rows + ", Invert=" + elapsed1 + "ms, Invert_Parallel=" + elapsed2 + "ms");
}

かなり明白な結果は、小さなタスク(マトリックスサイズ50)の場合、スレッドプールからのタスクの起動はシングルスレッドの実行よりも遅いことを示しています。

Matrix size=50,  Invert=  5ms,  InvertParallel=21ms
Matrix size=100, Invert= 19ms,  InvertParallel=24ms
Matrix size=200, Invert=137ms,  InvertParallel=44ms

(お詫び-私は新しいポスターなので、以下のメモからすべてのリンクを削除する必要がありました)

PS関連のS/O記事:「2つのスレッドを同時に開始する方法」、「Linux-スレッドとプロセスのスケジューリングの優先順位」

PSはい私は逆数を計算するためのより賢いアルゴリズムがあることを知っています。それはO(N ^ 2.376)としてスケーリングします。

PPSユーザーモードスケジューリング(WindowsではUMS)ユーザーモードスケジューリング(Windowsでは「UMS」)に慣れていませんが、役に立ちますか?

4

1 に答える 1

1

スレッド間でタスクを渡す場合、特にスレッドに大量のデータが関連付けられている場合は、重要なオーバーヘッドが発生するため、これまで見てきたように、小さなタスクのパフォーマンスが低下する可能性があります。複数のコアを使用する方が速いスイートスポットを見つける必要があります。

ところで、ワーカースレッドの1つを作成することで、わずかな改善を得ることができます。現在のスレッドは、1つのコンテキストスイッチとキャッシュ間のコピーを保存します。たとえば、コアが8つある場合は、1/7から7の他のスレッドを渡し、現在のスレッドで1/8を実行します。

于 2012-12-21T10:48:20.017 に答える