我一直在寻找一些方法来轻松地对我的一些简单分析代码进行多线程处理,因为我注意到numpy仅使用一个内核,尽管事实上它应该是多线程的。
我知道numpy是为多个内核配置的,因为我可以看到使用numpy.dot的测试使用了我的所有内核,因此我只是将Mean重新实现为点积,并且运行速度更快。是否有某些原因意味着不能自己快速运行?我发现较大的数组具有类似的行为,尽管该比率比示例中显示的3接近2。
我一直在阅读许多关于类似的numpy速度问题的文章,显然它的方式比我想象的要复杂。任何见解都将有所帮助,我宁愿仅使用均值,因为它更易读且代码更少,但我可能会改用基于点的均值。
In [27]: data = numpy.random.rand(10,10) In [28]: a = numpy.ones(10) In [29]: %timeit numpy.dot(data,a)/10.0 100000 loops, best of 3: 4.8 us per loop In [30]: %timeit numpy.mean(data,axis=1) 100000 loops, best of 3: 14.8 us per loop In [31]: numpy.dot(data,a)/10.0 - numpy.mean(data,axis=1) Out[31]: array([ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.11022302e-16, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.11022302e-16])
谁说它应该是多线程的?
numpy主要是为了在单个内核上尽可能快地设计,并且在需要时尽可能并行化。但是您仍然必须并行化它。
numpy
特别是,您可以同时对独立的子对象进行操作,并且慢速操作在可能的情况下会释放GIL,尽管“在可能的情况下”可能还远远不够。而且,numpy对象被设计为尽可能容易地在进程之间共享或传递,以利于使用multiprocessing。
multiprocessing
有一些自动并行化的专用方法,但大多数核心方法却没有。特别是,dot在可能的情况下在BLAS之上实现,并且BLAS在大多数平台上会自动并行化,但是mean以纯C代码实现。
dot
mean
有关详细信息,请参见使用numpy和scipy并行编程。
因此,您如何知道哪些方法是并行的,哪些不是?而且,在那些不是的情况下,您如何知道哪些可以很好地进行手动线程化,哪些需要进行多处理呢?
没有一个好的答案。您可以进行有根据的猜测(似乎X可能是在ATLAS之上实现的,而我的ATLAS副本是隐式线程化的),或者您可以阅读源代码。
但是通常,最好的办法是尝试并测试。如果代码使用一个内核的100%,另一个内核的0%,请添加手动线程。如果现在使用的是一个内核的100%,另一个内核的10%,并且运行速度几乎不快,请将多线程更改为多处理。(幸运的是,Python使此操作非常容易,特别是如果您使用来自的Executor类concurrent.futures或来自的Pool类multiprocessing。但是,如果阵列很大,您仍然经常需要考虑一些问题,并测试共享与传递的相对成本。 )
concurrent.futures
而且,正如kwatford所指出的,仅仅因为某种方法似乎不是隐式并行的,并不意味着它在下一版numpy,下一版BLAS或另一平台上不会并行。即使在安装了稍微不同的东西的机器上。因此,准备重新测试。然后执行类似的操作my_mean = numpy.mean,然后my_mean在任何地方使用,因此您只需将一行更改为即可my_mean = pool_threaded_mean。
my_mean = numpy.mean
my_mean
my_mean = pool_threaded_mean