nim 中比较两个字符串的函数比 python 慢

Wil*_*aum 3 python string bioinformatics nim-lang

我是 nim 的新手,但想用它来编写在 python 中使用的函数。我正在使用nimpyandnimporter将 nim 函数导入到 python 中。

python 中的这个函数:

def pcompare(a, b):
    letters = []
    for i, letter in enumerate(a):
        if letter != b[i]:
            letters.append(f'{letter}{i}{b[i]}')
    return letters
Run Code Online (Sandbox Code Playgroud)

a返回 string 中的字符与 string 中的字符不匹配的情况列表b

我在 nim 中编写了相同的函数:

compare.nim

import strformat
import nimpy

proc compare(a, b: string): seq[string] {.exportpy.} =
  for i, letter in a:
      if letter != b[i]:
        result.add(fmt"{letter}{i}{b[i]}")
Run Code Online (Sandbox Code Playgroud)

我可以将其导入到 python 中:import nimporter; import compare; 这些函数生成与 python 代码相同的输出。

然而,nim 函数比 python 代码慢得多!

a = 'aaaa' * 1000000
b = 'bbba' * 1000000

s = time.perf_counter()
ptest = pcompare(a, b)
e = time.perf_counter()
print(e - s)

s = time.perf_counter()
ntest = compare.compare(a, b)
e = time.perf_counter()
print(e - s)

output: 
python: 1.2781826159916818
nim: 3.607558835996315
Run Code Online (Sandbox Code Playgroud)

任何精通 nim 或其他编译语言的人都可以解释为什么会出现这种情况,并可能建议改进我的 nim 代码吗?

非常感谢所有评论!

谢谢,威廉

PMu*_*nch 9

这是一个不使用release开关进行编译的典型例子。如果您阅读编译 Nim 模块时的输出,您应该会看到如下行:

Hint: gc: refc; threads: on; opt: none (DEBUG BUILD, '-d:release' generates faster code)

编译-d:release对于在 Nim 中获得良好的速度至关重要。根据您正在做的事情,您还可以使用 获得更多(更少的运行时检查)-d:danger,并且根据工作负载,尝试新的--mm:arc内存管理模式也可能有所帮助。

因此,让我们比较一些数字,在我的机器上,您提供的代码给出了以下结果:

0.9097748600001978
5.580064230000062
Run Code Online (Sandbox Code Playgroud)

哦不,比你的数字还要糟糕,不太好!但如果我们打开-d:release开关,潮流就会转变:

0.9215690670002914
0.5742033299998184
Run Code Online (Sandbox Code Playgroud)

添加-d:danger又会带来一点点提升(在我的测试中比较更多样本,它始终稍微快一些):

0.9454311069998766
0.5695095589999255
Run Code Online (Sandbox Code Playgroud)

ARC 对于这种特定的工作负载没有帮助,LTO 也没有帮助,但是这两种方法对于其他事情可能表现更好。一般来说,您可以采取很多措施来加快 Nim 的速度,但到目前为止,最简单且最有效的方法是启用发布构建。