我正在尝试使用Numba在python中实现jaccard distance的最快版本
@nb.jit()
def nbjaccard(seq1, seq2):
set1, set2 = set(seq1), set(seq2)
return 1 - len(set1 & set2) / float(len(set1 | set2))
def jaccard(seq1, seq2):
set1, set2 = set(seq1), set(seq2)
return 1 - len(set1 & set2) / float(len(set1 | set2))
%%timeit
nbjaccard("compare this string","compare a different string")
——12.4毫秒
^{pr2}$-3.87毫秒
为什么麻木版本需要更长的时间?有没有办法加速?在
当我计时这两个函数时,
nbjaccard
需要~4.7微秒(在预热jit之后),而普通python函数使用numba0.32.0需要~3.2微秒。也就是说,在这种情况下,我不希望numba给您任何加速,因为目前在nopython
模式下基本上没有字符串支持。这意味着您将遍历python对象层,这通常与不使用jit运行没有什么不同,除非numba可以执行一些智能循环提升(即使用纯内部函数而不是python函数编译子块)。除了numba案例中输入的类型检查之外,您可能只需要支付一些小的开销。在我认为底线是,您正在尝试将numba用于当前未涵盖的用例。Numba真正擅长的地方是处理numpy数组和对数值标量值的操作或者可以推送到GPU的问题。在
在我看来,允许纯对象模式numba函数(或者如果numba实现了整个函数使用python对象,则没有警告),因为这些函数通常比纯python函数慢一些。在
Numba非常强大(与C扩展或Cython相比,无需类型声明就可以编写python代码的类型分派非常棒),但只有在它支持操作的情况下:
这意味着在“nopython”模式下不支持未列出的任何操作。如果numba不得不回到"object mode"那就小心了:
你的情况就是这样的:你完全是在对象模式下操作:
如您所见,每一个操作都在Python对象上操作(如每行末尾的
:: pyobject
所示)。这是因为numba
不支持str
s和set
s,所以这里绝对没有比这更快的了。但是你知道如何使用numpy数组或齐次列表(数值类型)来解决这个问题。在在我的电脑上,时间差要大得多(使用numba 0.32.0),但单个计时要快得多-微秒秒(
^{pr2}$10**-6
秒),而不是毫秒秒(10**-3
秒):注意,默认情况下
jit
是lazy,因此第一个调用应该在执行计时之前完成,因为它包括编译代码的时间。在不过,有一个优化你可以做:如果你知道两个集合的交集,你就可以计算联合的长度(正如@Paul Hankin在他的现在删除了答案中提到的那样):
这将导致以下(纯python)代码:
不是更快,而是更好。在
如果使用cython,还有一些改进空间:
这里的主要优点是,只需一次迭代,就可以创建
set2
并计算交集中元素的数量(根本不需要创建交集)!在相关问题 更多 >
编程相关推荐