gpt4 book ai didi

c - unicode 排序规则 NIF 运行速度比纯 Erlang 实现慢

转载 作者:行者123 更新时间:2023-12-02 02:13:57 24 4
gpt4 key购买 nike

我正在尝试通过将现有的 unicode 排序规则库(用 Erlang 编写)重写为 NIF 实现来优化它。主要原因是排序规则是 CPU 密集型操作。

实现链接:https://github.com/abhi-bit/merger

通过基于纯 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 倍。

我打开了eprof/fprof,但是对于NIF模块来说它们并没有多大用处,下面是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]

我确信,NIF 实现可以更快,因为我有一个基于使用动态数组的二进制堆的 unicode 排序规则的纯 C 实现,而且速度要快得多。

$ 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

我在这里提出的具体问题:

  • 由于 NIF 模块中的 Erlang <-> C 通信,预计会减慢多少?在这种情况下,纯 C 和 NIF 实现之间的速度可能会降低 30 倍或更多
  • 哪些工具可用于调试 NIF 相关的速度减慢(如本例)?我尝试使用 perf top 来查看函数调用,顶部的函数调用(显示了一些十六进制地址)来自“beam.smp”。
  • 我应该考虑优化 NIF 的哪些可能领域?例如:我听说应该将 Erlang 与 C 之间的数据传输保持在最低限度,反之亦然,还有更多这样的领域需要考虑吗?

最佳答案

调用 NIF 的开销很小。当 Erlang 运行时加载一个加载 NIF 的模块时,它会使用模拟器指令修补该模块的 Beam 代码以调用 NIF。在调用实现 NIF 的 C 函数之前,指令本身仅执行少量设置。这不是导致性能问题的区域。

分析 NIF 与分析任何其他 C/C++ 代码非常相似。从您的 Makefile 来看,您似乎正在 OS X 上开发此代码。在该平台上,假设您安装了 XCode,则可以使用 Instruments application使用 CPU Samples 工具来查看您的代码在哪里花费了大部分时间。在 Linux 上,您可以使用 callgrind tool of valgrindErlang emulator built with valgrind support 一起衡量您的代码。

例如,如果您在代码中使用这些工具,您会发现 perf_merger:main/1 大部分时间都花在 merger_nif_heap_get 上,这反过来,在 Collat​​eJSON 中花费了大量时间。该函数似乎调用了 convertUTF8toUCharcreateStringFromJSON 相当多。您的 NIF 似乎还执行了大量内存分配。这些是您应该重点关注的领域,以加快您的代码速度。

关于c - unicode 排序规则 NIF 运行速度比纯 Erlang 实现慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34557134/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com