Python np.array==num比较是否非常慢?可以使用多处理来加速它吗?

Python np.array==num比较是否非常慢?可以使用多处理来加速它吗?,python,performance,numpy,python-multiprocessing,pool,Python,Performance,Numpy,Python Multiprocessing,Pool,在python中,大型np.array与单个数字之间的比较是否非常低?我使用line_profiler查找代码中的瓶颈。瓶颈只是一个1d np.array与常量之间的简单比较。它占总运行时间的80%。我做错了什么导致它这么慢吗?有什么办法可以加速吗 我尝试使用多处理,但是,在测试代码(代码段2)中,使用多处理比按顺序运行和直接使用map要慢。有人能解释这种现象吗 如有任何意见或建议,我们将不胜感激 片段1: 行#每次命中的命中次数%时间行内容 38 12635 305767927.0 24200

在python中,大型np.array与单个数字之间的比较是否非常低?我使用line_profiler查找代码中的瓶颈。瓶颈只是一个1d np.array与常量之间的简单比较。它占总运行时间的80%。我做错了什么导致它这么慢吗?有什么办法可以加速吗

我尝试使用多处理,但是,在测试代码(代码段2)中,使用多处理比按顺序运行和直接使用map要慢。有人能解释这种现象吗

如有任何意见或建议,我们将不胜感激

片段1:

行#每次命中的命中次数%时间行内容

38 12635 305767927.0 24200.1 80.0 res=map(逻辑相等,装配)

F是一个整型(281900,6)np数组

片段2:

import numpy as np
from multiprocessing import Pool
import time

y=np.random.randint(2, 20, size=10000000)

def logicalEqual(x):
    return y == x

p=Pool()
start = time.time()
res0=p.map(logicalEqual, [1,2,3,4,5,7,8,9,10,11,12,13,14,15])
# p.close()
# p.join()
runtime = time.time()-start
print(f'runtime using multiprocessing.Pool is {runtime}')

res1 = []
start = time.time()
for x in [1,2,3,4,5,7,8,9,10,11,12,13,14,15]:
    res1.append(logicalEqual(x))
runtime = time.time()-start
print(f'sequential runtime is {runtime}')


start = time.time()
res2=list(map(logicalEqual,[1,2,3,4,5,7,8,9,10,11,12,13,14,15]))
runtime = time.time()-start
print(f'runtime is {runtime}')

runtime using multiprocessing.Pool is 0.3612203598022461
sequential runtime is 0.17401981353759766
runtime is  0.19697237014770508

数组比较很快,因为它是用C代码而不是Python完成的

x=np.rand.rand(1000000)
y=4.5
测试=0.55
%timeit x==测试
每个回路386µs±4.68µs(7次运行的平均值±标准偏差,每个1000个回路)
%timeit y==测试
每个回路33.2纳秒±0.121纳秒(7次运行的平均值±标准偏差,每个10000000个回路)

因此,比较一个Python浮点值与另一个Python浮点值需要33*10^-9秒,而比较1E6 numpy浮点值只需要386µs/33 ns~=11700倍的时间,尽管比较了1000000个以上的值。整数也是如此(377µs vs 34 ns)。但正如Dunes在评论中提到的,比较很多值需要很多周期。对此您无能为力。

数组比较很快,因为它是用C代码而不是Python完成的

x=np.rand.rand(1000000)
y=4.5
测试=0.55
%timeit x==测试
每个回路386µs±4.68µs(7次运行的平均值±标准偏差,每个1000个回路)
%timeit y==测试
每个回路33.2纳秒±0.121纳秒(7次运行的平均值±标准偏差,每个10000000个回路)


因此,比较一个Python浮点值与另一个Python浮点值需要33*10^-9秒,而比较1E6 numpy浮点值只需要386µs/33 ns~=11700倍的时间,尽管比较了1000000个以上的值。整数也是如此(377µs vs 34 ns)。但正如Dunes在评论中提到的,比较很多值需要很多周期。对此您无能为力。

map
实际上不会运行该函数,除非您在Python3上迭代生成的迭代器。正如您可能猜到的,不运行函数相当快。@user2357112是的,您是对的。我忽略了那一点。现在我纠正了问题中误导性的部分。非常感谢。F有多大?什么是
x
,什么是
F
的数据类型?F是int类型np.array sied of(281900,6)我想你没有意识到你要求程序做了多少工作。实际上,您要求程序将10个数字与1000万个其他数字进行比较。这大约是十亿分之一。CPU的额定频率通常为GHz(或每秒数十亿次操作)。因此,您的程序运行大约需要十分之一秒。
map
实际上不会运行该函数,除非您在Python3上迭代生成的迭代器。正如您可能猜到的,不运行函数相当快。@user2357112是的,您是对的。我忽略了那一点。现在我纠正了问题中误导性的部分。非常感谢。F有多大?什么是
x
,什么是
F
的数据类型?F是int类型np.array sied of(281900,6)我想你没有意识到你要求程序做了多少工作。实际上,您要求程序将10个数字与1000万个其他数字进行比较。这大约是十亿分之一。CPU的额定频率通常为GHz(或每秒数十亿次操作)。因此,预计您的程序运行时间约为十分之一秒。非常感谢您的分析和回答我的问题。看起来它达到了CPU时钟频率。但是我可以使用多处理来并行计算吗?如代码段2中所示,multiprocessing.Pool()并没有加速计算。我不想把80%的运行时间花在简单的逻辑比较上。我不明白为什么在这种情况下,多处理并没有提高性能,尽管我在python中看到了多处理的性能提高。一个进程的启动时间可能会阻碍这里的结果。列出Python中进程的成本。这意味着您只能在运行时间较长的TAK中看到加速,与总运行时间相比,启动成本较低。@AlbertGLieu因为序列化数组、将数组发送到新进程、反序列化数组、然后进行计算的开销,然后再次序列化并将其发送回并不值得获得任何并行性收益。特别是对于如此小的.Juanpa数组,我理解设置多处理所造成的开销,但我的代码中80%的运行时都是通过这样一个简单的比较得到的。我知道我的np.array有多大,以及进行了多少次比较。有没有办法加速比较?皮库达能帮上忙吗?非常感谢你的分析和回答我的问题。看起来它达到了CPU时钟频率。但是我可以使用多处理来并行计算吗?如代码段2中所示,multiprocessing.Pool()并没有加速计算。我不想把80%的运行时间花在简单的逻辑比较上。我不明白为什么在这种情况下,多处理并没有提高性能,尽管我在python中看到了多处理的性能提高。一个进程的启动时间可能会阻碍这里的结果。列出Python中进程的成本。这意味着您只能在运行时间较长的TAK中看到加速,与总运行时间相比,启动成本较低。@AlbertGLieu因为序列化arr的开销较大
import numpy as np
from multiprocessing import Pool
import time

y=np.random.randint(2, 20, size=10000000)

def logicalEqual(x):
    return y == x

p=Pool()
start = time.time()
res0=p.map(logicalEqual, [1,2,3,4,5,7,8,9,10,11,12,13,14,15])
# p.close()
# p.join()
runtime = time.time()-start
print(f'runtime using multiprocessing.Pool is {runtime}')

res1 = []
start = time.time()
for x in [1,2,3,4,5,7,8,9,10,11,12,13,14,15]:
    res1.append(logicalEqual(x))
runtime = time.time()-start
print(f'sequential runtime is {runtime}')


start = time.time()
res2=list(map(logicalEqual,[1,2,3,4,5,7,8,9,10,11,12,13,14,15]))
runtime = time.time()-start
print(f'runtime is {runtime}')

runtime using multiprocessing.Pool is 0.3612203598022461
sequential runtime is 0.17401981353759766
runtime is  0.19697237014770508