速さこそ正義!
かえるのクーの助手の「井戸中 聖」(いとなか セイ)でございます。
C++とRustの「連想配列/HashMap」がことのほか遅いことがわかって、一瞬そんなにも速くないイメージを持ってしまいました。
「C++とRUSTが遅い訳ないじゃん。」という天の声が聞こえました。また、大量データで速度を求めるなら『ハッシュ(unordered_map)」ではなく「マップ(map)」を用いるべきである。初心者にも程がある。』という地の声も聞こえました。C++は初心者だと思ってましたが、それですらなく「初めて」作成したことに気が付きました。(言い訳:UNIX C言語なら自信がありました)
なので、通常の動的配列(ベクトル系)で爆速なのを確認するだけの2番煎じ記事です。
本当はベクトル系ではなく、array系(固定長配列)で比較しようと思ったのですが、3億弱程度の配列定義でコンパイルが通らなくなり、より実用性の高いvectorでの比較となります。
本題の「何故Javaで用もないのにマルチスレッド処理になるのか?」については調査進捗がございませんので、ケイゾクとさせていただきます。
比較レギュレーションは以下のとおり
・簡単なオブジェクト(クラスもしくは構造体のインスタンス)を4億個準備する。(パラメータ値あり)
・オブジェクトをVectorに格納する。(Vectorの個数はコーディング定義時に指定してよい)
・上記のデータの準備にどれくらいかかるか測定する。
・キャッシュの影響をなくすため、そのまま30秒待つ。
・4億個のインスタンスを順次取得してパラメータ値を加算する。
・加算した値を表示する。
・加算にかかる時間を計測する。
結果:
ご覧のとおり、RustとC++は爆速です。20~30GB程度のメモリを一気にアロケーションして一気に計算して一気に解放します。爽快です!気をよくして、主マシンのメモリUP↑計画(256GB化)を前倒そうと思います。
測定 |
Java (List) |
Python※ (Pypy) |
JavaScript (Node.js) |
Rust | C++ |
---|---|---|---|---|---|
データ準備(sec) | 8.107 |
184.913 (112.408) |
エラー発生! ※1億個だと30.892
|
1.158 | 1.408 |
データ集計 (sec) |
1.966 |
12.420 (1.343) |
※1億個だと 0.555 |
0.464 | 0.429 |
所感 |
善戦だと思います。 マルチスレッド します。 |
通常配列は不得意。 |
メモリ系エラー | 爆速です。 | 爆速です。 |
※PythonはList([])を使用しました。
※JavaScriptはエラーが発生しました。heapを32GBに設定して1億くらいまではいけたのですが、配列数が多すぎて Fatal JavaScript invalid size errorでお亡くなり。
十分速くていい感じなのですが、メモリを増強してオブジェクトを160億個(ただし分散/永続化含む)まで作成するので、いまのところJavaScriptは対象外とします。。。
JavaScript (オブジェクト1億まで):メインは1スレッドのようですが、他3~4スレッドが補助しているようです。(おそらくはGC系か?)
他言語のCPU負荷は前回とおんなじ感じなので省略します。
その他:
Javaはvectorが正式に非推奨になっている訳ではないようですが、公式に「vectorではなくlistを使用するよう推奨する」と記載があるのでList/ArrayListで確認しました。(確かに2倍くらいの速度差がありました。)そういえばjavaでvectorは使ったことがなかったです。
(蛇足)ソース
ソースは前回とほぼ同じなので、貼るまでもないのですが、1年後くらいにあれ?どうだっけ?と気になりそうなので、いちおう変更分を貼っておきます。
Java
import java.util.ArrayList;import java.util.List;
List<Neuron> nList = new ArrayList<Neuron>(NEURO_COUT);
}
Python
# 初期化は固定値にしてみる
neuro_array = [ Neuro(bias=1.01, activate=1.01)] * NEURO_COUNT
# 初期化してあるので、appendでなく置き換えられる(appendは超絶遅いので使わない)
for i in range(NEURO_COUNT):
neuro_array[i] = Neuro(bias=1.01, activate=float(i))
# データを件数分加算
for i in range(NEURO_COUNT):
sum += neuro_array[i].activate
dummy += neuro_array[i].bias
JavaScript:ぜんぶはります
2億個のオブジェクトは無理でした
PS C:\work\node\test01> node --max-heap-size=32768 test01.js
Hello World!(Java Script)
#
# Fatal error in , line 0
# Fatal JavaScript invalid size error 169220804
#
#FailureMessage Object: 00000086483FEA80
1: 00007FF76F36D51F node_api_throw_syntax_error+175743
2: 00007FF76F2837BF v8::CTypeInfoBuilder<void>::Build+12703
3: 00007FF77012D852 V8_Fatal+162
4: 00007FF76FC3AB05 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArray+101
5: 00007FF76FABFF43 v8::internal::FeedbackNexus::ic_state+65795
6: 00007FF76FADEAC0 v8::Message::GetIsolate+15600
7: 00007FF76F92AE10 v8::internal::CompilationCache::IsEnabledScriptAndEval+25952
8: 00007FF76FE38051 v8::internal::SetupIsolateDelegate::SetupHeap+558193
9: 00007FF6EFF8F6BC
PS C:\work\node\test01>