- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 Numba 在 python 中实现最快的 jaccard 距离版本
@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 毫秒
%%timeit
jaccard("compare this string","compare a different string")
--3.87 毫秒
为什么 numba 版本需要更长的时间?有什么方法可以加速吗?
最佳答案
在我看来,允许纯对象模式 numba 函数是一个设计错误(或者如果 numba 意识到整个函数使用 python 对象则没有警告)——因为这些是通常比纯 Python 函数慢一点。
Numba 非常强大(类型分派(dispatch)和您可以在没有类型声明的情况下编写 python 代码 - 与 C 扩展或 Cython 相比 - 真的很棒)但只有当它支持操作时:
这意味着“nopython”模式不支持任何未在此处列出的操作。如果 numba 必须退回到 "object mode"然后小心:
object mode
A Numba compilation mode that generates code that handles all values as Python objects and uses the Python C API to perform all operations on those objects. Code compiled in object mode will often run no faster than Python interpreted code, unless the Numba compiler can take advantage of loop-jitting.
这正是您的情况:您纯粹在对象模式下操作:
>>> nbjaccard.inspect_types()
[...]
# --- LINE 3 ---
# seq1 = arg(0, name=seq1) :: pyobject
# seq2 = arg(1, name=seq2) :: pyobject
# $0.1 = global(set: <class 'set'>) :: pyobject
# $0.3 = call $0.1(seq1) :: pyobject
# $0.4 = global(set: <class 'set'>) :: pyobject
# $0.6 = call $0.4(seq2) :: pyobject
# set1 = $0.3 :: pyobject
# set2 = $0.6 :: pyobject
set1, set2 = set(seq1), set(seq2)
# --- LINE 4 ---
# $const0.7 = const(int, 1) :: pyobject
# $0.8 = global(len: <built-in function len>) :: pyobject
# $0.11 = set1 & set2 :: pyobject
# $0.12 = call $0.8($0.11) :: pyobject
# $0.13 = global(float: <class 'float'>) :: pyobject
# $0.14 = global(len: <built-in function len>) :: pyobject
# $0.17 = set1 | set2 :: pyobject
# $0.18 = call $0.14($0.17) :: pyobject
# $0.19 = call $0.13($0.18) :: pyobject
# $0.20 = $0.12 / $0.19 :: pyobject
# $0.21 = $const0.7 - $0.20 :: pyobject
# $0.22 = cast(value=$0.21) :: pyobject
# return $0.22
return 1 - len(set1 & set2) / float(len(set1 | set2))
如您所见,每个操作都对 Python 对象进行操作(如每行末尾的 ::pyobject
所示)。那是因为 numba
不支持 str
和 set
。所以这里绝对没有什么比这更快的了。除非您知道如何使用 numpy 数组或同类列表(数字类型)解决此问题。
在我的电脑上,时差要大得多(使用 numba 0.32.0),但个别计时要快得多 - 微秒(10**-6
秒) 而不是 毫秒秒(10**-3
秒):
%timeit nbjaccard("compare this string","compare a different string")
10000 loops, best of 3: 84.4 µs per loop
%timeit jaccard("compare this string","compare a different string")
100000 loops, best of 3: 15.9 µs per loop
请注意 jit
默认为 lazy ,因此第一次调用应该在您为执行计时之前完成 - 因为它包括编译代码的时间。
不过,您可以进行一种优化:如果您知道两个集合的交集,则可以计算并集的长度(正如@Paul Hankin 在他的现已删除 回答中提到的):
len(union) = len(set1) + len(set2) - len(intersection)
这将导致以下(纯 python)代码:
def jaccard2(seq1, seq2):
set1, set2 = set(seq1), set(seq2)
num_intersection = len(set1 & set2)
return 1 - num_intersection / float(len(set1) + len(set2) - num_intersection)
%timeit jaccard2("compare this string","compare a different string")
100000 loops, best of 3: 13.7 µs per loop
不是更快 - 但更好。
如果您使用 cython,还有一些改进空间:
%load_ext cython
%%cython
def cyjaccard(seq1, seq2):
cdef set set1 = set(seq1)
cdef set set2 = set()
cdef Py_ssize_t length_intersect = 0
for char in seq2:
if char not in set2:
if char in set1:
length_intersect += 1
set2.add(char)
return 1 - (length_intersect / float(len(set1) + len(set2) - length_intersect))
%timeit cyjaccard("compare this string","compare a different string")
100000 loops, best of 3: 7.97 µs per loop
这里的主要优点是只需一次迭代就可以创建 set2
并计算交集中的元素数量(根本不需要创建交集)!
关于python - 使用 numba 优化 Jaccard 距离性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43596535/
我想将一个类对象传递给一个函数。我可以让它工作,但我想知道是否有我可以分配的类型?我有一个我正在尝试做的“最小”示例。 spec = [("a", float64),("b",float64)] @j
我有一个简单的函数来对扑克手牌进行排序(手牌是字符串)。 我用 rA,rB = rank(a),rank(b) 调用它,这是我的实现。没有 @jit(nopython=True) 也能很好地工作,但是
我在这里有一个简单的例子来帮助我理解使用 numba 和 cython。我是 numba 和 cython 的新手。我已经尽力结合所有技巧来使 numba 更快,并且在某种程度上,cython 也是如
我正在使用 numbas @jit 装饰器在 python 中添加两个 numpy 数组。如果我使用 @jit 与 python 相比,性能是如此之高。 然而,即使我传入 @numba.jit(nop
我需要为通用指标构建相异矩阵。由于我需要算法快速运行,所以我在 nopython 模式下使用了 numba 0.35。这是我的代码 import numpy as np from numba impo
Numba Cuda 有 syncthreads() 来同步一个 block 中的所有线程。如何在不退出当前内核的情况下同步网格中的所有 block ? 在 C-Cuda 中有一个 cooperati
有人尝试在Google合作伙伴中使用numba吗?我只是不知道如何在此环境中进行设置。 此刻,我陷入了错误library nvvm not found。 最佳答案 将此代码复制到单元格中。这个对我有用
我想编写一个函数,它既可以作为 jitted 函数运行,也可以作为普通 python 或对象模式 numba 运行,具体取决于 numba 是否能够进行类型推断。我实际上更喜欢普通的 python,但
我有一个非常简单的问题我无法解决。 我正在使用 Numba 和 Cuda。我有一个列表 T=[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0] 我想要一个包含列表元素的元组,如
我正在测试一些采用 numpy 数组的函数的 numba 性能,并比较: import numpy as np from numba import jit, vectorize, float64 im
我正在使用 Scipy 的 interpolate.interp1d 在 Python3 中插入一维数组。我想将它与 numba 一起使用,但不支持 scipy 和此功能。是否有 numba 支持
我是 Numba 的新手,我正在尝试使用 Numba(版本 0.54.1)在 Python 中实现旧的 Fortran 代码,但是当我添加 parallel = True 时,程序实际上变慢了.我的程
我需要在 Python 中创建一个位数组。到目前为止,我发现可以使用 bitarray 生成非常节省内存的数组。模块。 然而,我的最终目的是使用来自Numba 的@vectorize 装饰器。 . N
我认为这是一个简单的问题,但我发现 numba 文档缺乏关于如何将字符串类型与 numpy 数组和字典一起使用的信息。我有一个我想使用 numba 的函数,它需要一个邮政编码列表,然后是一个映射邮政编
假设我有两个功能 def my_sub1(a): return a + 2 def my_main(a): a += 1 b = mysub1(a) return b
在以下用于逻辑比较的 numba 编译函数中,性能下降的原因可能是什么: from numba import njit t = (True, 'and_', False) #@njit(boolean
我的代码使用如下列表的笛卡尔积: import itertools cartesian_product = itertools.product(list('ABCDEF'), repeat=n) n可
我正在使用 Numba(版本 0.37.0)来优化 GPU 代码。我想使用组合矢量化函数(使用 Numba 的 @vectorize 装饰器)。 导入和数据: import numpy as np f
我想知道在 numba 函数中计算两个列表的交集的最快方法。只是为了澄清:两个列表的交集示例: Input : lst1 = [15, 9, 10, 56, 23, 78, 5, 4, 9] lst2
我正在使用 Numba 非 python 模式和一些 NumPy 函数。 @njit def invert(W, copy=True): ''' Inverts elementwise
我是一名优秀的程序员,十分优秀!