3

既存の Unicode 照合ライブラリ (Erlang で記述) を NIF 実装として書き直して最適化しようとしています。主な理由は、照合が CPU を集中的に使用する操作であるためです。

実装へのリンク: https://github.com/abhi-bit/merger

Pure Erlang ベースの優先キューによる 1M 行の Unicode 照合:

erlc *.erl; ERL_LIBS="..:$ERL_LIBS" erl -noshell -s perf_couch_skew main 1000000 -s init stop
Queue size: 1000000
12321.649 ms

NIF ベースの二項ヒープによる 1M 行の Unicode 照合:

erlc *.erl; ERL_LIBS="..:$ERL_LIBS" erl -noshell -s perf_merger main 1000000 -s init stop
Queue size: 1000000
15871.965 ms

これは珍しいことです。おそらく最大 10 倍高速になると予想していました。

オンにしましたがeproffprofNIF モジュールに関してはあまり役に立ちません。以下はeprof、主要な機能について述べたものです。

FUNCTION                                         CALLS      %     TIME  [uS / CALLS]
--------                                         -----    ---     ----  [----------]
merger:new/0                                         1   0.00        0  [      0.00]
merger:new/2                                         1   0.00        0  [      0.00]
merger:size/1                                   100002   0.31    19928  [      0.20]
merger:in/3                                     100000   3.29   210620  [      2.11]
erlang:put/2                                   2000000   6.63   424292  [      0.21]
merger:out/1                                    100000  14.35   918834  [      9.19]

動的配列を使用したバイナリヒープに基づくユニコード照合の純粋な C 実装があり、はるかに高速であるため、NIF 実装を高速化できると確信しています。

$ make
gcc -I/usr/local/Cellar/icu4c/55.1/include  -L/usr/local/Cellar/icu4c/55.1/lib  min_heap.c collate_json.c kway_merge.c kway_merge_test.c -o output -licui18n -licuuc -licudata
./output
Merging 1 arrays each of size 1000000
mergeKArrays took 84.626ms

私がここに持っている具体的な質問:

  • Erlang <-> NIF モジュールでの C 通信により、どれくらいの速度低下が予想されますか? この場合、純粋な C と NIF の実装の間で速度がおそらく 30 倍以上になります。
  • この場合のように、NIF 関連のスローダウンをデバッグするのに役立つツールは何ですか? 関数呼び出しを確認するために使用perf topしてみましたが、上位のもの (一部の 16 進アドレスが表示されていました) は「beam.smp」からのものでした。
  • NIF を最適化するために検討すべき領域は何ですか? 例: Erlang から C へのデータ転送、およびその逆のデータ転送を最小限に抑える必要があると聞いたことがありますが、他に考慮すべき領域はありますか?
4

1 に答える 1