研究プロジェクトのために、並列計算を行うために多数の先物を使用する Scala アプリケーションを作成しました。私のローカル マシン (4 コア) では、コンピューター サイエンス研究所のメニー コア サーバー (64 コア) よりもコードが高速に実行されることに気付きました。今、私はこれがなぜなのか知りたいです。
タスクの詳細
タスクは、m 節にランダムに分散された n 個の異なる変数を使用してランダムなブール k-CNF 式を作成し、どの m/n の組み合わせで式が解ける確率がさまざまなランダム分布で 50% を下回るかを確認することでした。このために、確率論的 k-SAT アルゴリズム、節ジェネレーター、およびその他のコードを実装しました。コアは、ジェネレーター関数と同様に n と m を受け取り、100 個の先物を実行して結果を待つ関数です。関数は次のようになります。
問題のコード
def avgNonvalidClauses(n: Int, m: Int)(implicit clauseGenerator: ClauseGenerator) = {
val startTime = System.nanoTime
/** how man iteration to build the average **/
val TRIES = 100
// do TRIES iterations in parallel
val tasks = for (i <- 0 until TRIES) yield future[Option[Config]] {
val clause = clauseGenerator(m, n)
val solution = CNFSolver.probKSat(clause)
solution
}
/* wait for all threads to finish and collect the results. we will only wait
* at most TRIES * 100ms (note: flatten filters out all
* None's) */
val results = awaitAll(100 * TRIES, tasks: _*).asInstanceOf[List[Option[Option[Config]]]].flatten
val millis = Duration(System.nanoTime - startTime, NANOSECONDS).toMillis
val avg = (results count (_.isDefined)) / results.length.toFloat
println(s"n=$n, m=$m => $avg ($millis ms)")
avg
}
問題
私のローカルマシンでは、これらの結果が得られます
[info] Running Main
n=20, m=120 => 0.0 (8885 ms)
n=21, m=121 => 0.0 (9115 ms)
n=22, m=122 => 0.0 (8724 ms)
n=23, m=123 => 0.0 (8433 ms)
n=24, m=124 => 0.0 (8544 ms)
n=25, m=125 => 0.0 (8858 ms)
[success] Total time: 53 s, completed Jan 9, 2013 8:21:30 PM
64 コアのサーバーでは、次のようになります。
[info] Running Main
n=20, m=120 => 0.0 (43200 ms)
n=21, m=121 => 0.0 (38826 ms)
n=22, m=122 => 0.0 (38728 ms)
n=23, m=123 => 0.0 (32737 ms)
n=24, m=124 => 0.0 (41196 ms)
n=25, m=125 => 0.0 (42323 ms)
[success] Total time: 245 s, completed 09.01.2013 20:28:22
ただし、両方のマシンで全負荷 (サーバーの平均負荷は約 60 ~ 65) であるため、十分なスレッドが実行されています。どうしてこれなの?私は何か完全に間違っていますか?
私のローカルマシンには「AMD Phenom(tm) II X4 955 Processor」CPU が搭載されており、サーバーは「AMD Opteron(TM) Processor 6272」を使用しています。ローカル CPU には 6800 の bogomips があり、サーバーには 4200 があります。したがって、ローカル CPU は 1/3 高速ですが、サーバーには 12 倍のコアがあります。
追加
私のコードの縮小された例が github にプッシュされている場合は、興味がある場合は自分で試すことができます: https://github.com/Blattlaus/algodemo (これは Scala 2.10 を使用する sbt プロジェクトです)。
アップデート
- 乱数ジェネレーターに 42 をシードすることでランダム性を排除しました。これは何も変更しません
- テストセットを変更しました。結果はさらに驚くべきものになりました (サーバーは 5 倍遅いです!) 注: 解決できない節の平均パーセンテージのすべての出力は、入力のために zeor です。これは正常であり、予期されたものです。
- CPU に関する追加情報
- サーバー上で Random.nextInt() の呼び出しが 10 倍遅いことに気付きました。すべての呼び出しをヘルパーでラップしました。これは、出力が 10 ミリ秒よりも遅い場合にコンソールに出力されるランタイムを測定します。私のローカルマシンでは、いくつか取得できますが、通常は約 10 ~ 20 ミリ秒です。サーバーでは、多くの mure 呼び出しが発生し、それらは 100 ミリ秒を超える傾向があります。これが問題でしょうか?