【问题标题】:is np.array == num comparison very slow? Can multiprocessing be used to accelerate it?np.array == num 比较很慢吗?可以使用多处理来加速吗?
【发布时间】:2019-06-04 18:57:33
【问题描述】:

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

我尝试使用多处理,但是,在测试代码(sn-p 2)中,使用多处理比按顺序运行并直接使用映射要慢。谁能解释这种现象?

衷心感谢任何 cmets 或建议。

片段 1:

Line # Hits Time Per Hit %Time Line Contents

38 12635 305767927.0 24200.1 80.0 res = map(logicalEqual,assembly)

def logicalEqual(x):
         return F[:,-1] == x

assembly = [1,2,3,4,5,7,8,9,...,25]

F 是一个 int 类型的 (281900, 6) np.array

片段 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

【问题讨论】:

  • map 不会真正运行函数,除非你在 Python 3 上迭代生成的迭代器。不运行函数会很快,你可能猜到了。
  • @user2357112 是的,你是对的。我忽略了这一点。现在我纠正了我的问题中的误导部分。非常感谢。
  • F 有多大? x是什么,F的数据类型是什么?
  • F 是 int 类型 np.array sied of (281900, 6)
  • 我认为你没有意识到你要求程序做多少工作。您实际上是在要求程序将约 10 个数字与约 1000 万个其他数字进行比较。这大约是十亿的 1/10。 CPU 通常以另一个 GHz 为单位(或每秒数十亿次操作)。因此,预计您的程序运行时间约为 1/10 秒。

标签: python performance numpy python-multiprocessing pool


【解决方案1】:

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

x = np.random.rand(1000000)
y = 4.5
test = 0.55
%timeit x == test
386 µs ± 4.68 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit y == test
33.2 ns ± 0.121 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

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

【讨论】:

  • 非常感谢您的分析和回答我的问题。看起来它达到了 CPU 时钟频率。但是我可以使用多处理来并行计算吗?如 sn-p 2 所示,multiprocessing.Pool() 没有加速计算。我不想将 80% 的运行时间花在简单的逻辑比较上。我不明白为什么在这种情况下多处理没有提高性能,尽管我已经看到在 python 中使用多处理实现了性能提升。
  • 进程的启动时间可能会阻碍此处的结果。 This answer 列出了 Python 中进程的成本。这意味着您只会看到运行时间较长的任务的加速,与总运行时间相比,启动成本较低。
  • @AlbertGLieu 因为序列化数组、将其发送到新进程、然后对其进行反序列化、然后进行计算、然后再次对其进行序列化并将其发送回的开销是不值得任何并行性的收益。特别是对于这么小的数组。
  • Juanpa,我理解多处理设置带来的开销,但是我的代码中 80% 的运行时间都是通过这样一个简单的比较来完成的。我知道我的 np.array 有多大以及进行了多少次比较。有什么方法可以加速比较? Pycuda 会对此有所帮助吗?
猜你喜欢
  • 2019-06-28
  • 1970-01-01
  • 2011-01-17
  • 2016-05-19
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 2014-08-01
相关资源
最近更新 更多