Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么不是';是指多线程?_Python_Multithreading_Performance_Numpy - Fatal编程技术网

Python 为什么不是';是指多线程?

Python 为什么不是';是指多线程?,python,multithreading,performance,numpy,Python,Multithreading,Performance,Numpy,自从我注意到numpy只使用了一个内核以来,我一直在寻找方法来轻松地多线程处理我的一些简单分析代码,尽管事实上它应该是多线程的 我知道numpy是为多核配置的,因为我可以看到使用numpy的测试。dot使用我所有的核,所以我只是将mean重新实现为dot产品,它运行得更快。是不是有什么原因让我们不能自己跑这么快?对于较大的阵列,我发现了类似的行为,尽管这个比率比我的示例中显示的3接近2 我一直在读一些关于类似numpy速度问题的帖子,显然它的方式比我想象的要复杂得多。任何见解都会有帮助,我更喜欢

自从我注意到numpy只使用了一个内核以来,我一直在寻找方法来轻松地多线程处理我的一些简单分析代码,尽管事实上它应该是多线程的

我知道numpy是为多核配置的,因为我可以看到使用numpy的测试。dot使用我所有的核,所以我只是将mean重新实现为dot产品,它运行得更快。是不是有什么原因让我们不能自己跑这么快?对于较大的阵列,我发现了类似的行为,尽管这个比率比我的示例中显示的3接近2

我一直在读一些关于类似numpy速度问题的帖子,显然它的方式比我想象的要复杂得多。任何见解都会有帮助,我更喜欢使用mean,因为它可读性更强,代码更少,但我可能会切换到基于点的方法

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])

基本上,因为BLAS库有一个优化的点积,他们可以很容易地调用本质上是并行的
dot
。他们承认他们可以扩展numpy以并行其他操作,但选择不走这条路。但是,他们给出了一些关于如何并行化numpy代码的提示(基本上是在N个核之间划分工作(例如,N=4),将数组拆分为N个子数组,并将每个子数组的作业发送到其自己的线程,然后合并结果)

见:

使用并行原语 numpy的一大优点是可以非常清晰地表达数组操作。例如,要计算矩阵A和矩阵B的乘积,只需执行以下操作:

>C=numpy.dot(A,B)

不仅读写简单明了,因为numpy知道你想做一个矩阵点积,所以它可以使用作为“BLAS”(基本线性代数子程序)一部分的优化实现。这通常是一个经过仔细调整的库,通过利用缓存内存和汇编程序实现在硬件上尽可能快地运行。但是现在很多架构都有一个BLAS,它也利用了多核机器。如果您的numpy/scipy是使用其中一个进行编译的,那么dot()将在不执行任何操作的情况下并行计算(如果速度更快的话)。类似于其他矩阵运算,如反演、奇异值分解、行列式等。例如,开源库ATLAS允许在编译时选择并行级别(线程数)。Intel专有的MKL库提供了在运行时选择并行级别的可能性。还有GOTO库,允许运行时选择并行级别。这是一个商业产品,但源代码免费分发供学术使用

最后,scipy/numpy不会并行化像

>A=B+C

>A=numpy.sin(B)

>A=scipy.stats.norm.isf(B)

这些操作按顺序运行,不利用多核机器(但请参见下文)。原则上,这可以在不做太多工作的情况下改变。OpenMP是C语言的一个扩展,它允许编译器为适当注释的循环(和其他东西)生成并行化代码。如果有人坐下来在numpy(可能还有scipy)中注释几个核心循环,然后有人在打开OpenMP的情况下编译numpy/scipy,上述三个循环将自动并行运行。当然,在现实中,人们可能想要一些运行时控制——例如,如果一个人计划在同一台多处理器机器上运行多个作业,那么他可能想要关闭自动并行化

自从我注意到numpy只使用了一个内核以来,我一直在寻找方法来轻松地多线程处理我的一些简单分析代码,尽管事实上它应该是多线程的

谁说它应该是多线程的

numpy
主要设计为在单个内核上尽可能快,并且在需要时尽可能并行。但你还是要把它并行化

特别是,您可以同时对独立的子对象进行操作,如果可能,慢速操作会释放GIL,尽管“如果可能”可能还不够。另外,
numpy
对象被设计为尽可能容易地在进程之间共享或传递,以便于使用
多处理

有一些专门的方法是自动并行的,但大多数核心方法不是。特别是,
dot
在可能的情况下在BLAS之上实现,BLAS在大多数平台上自动并行,但
mean
在普通C代码中实现

有关详细信息,请参阅


那么,您如何知道哪些方法是并行的,哪些不是?还有,在那些没有的情况下,您如何知道哪些可以很好地手动线程化,哪些需要多处理

没有好的答案。您可以进行有根据的猜测(X看起来可能是在ATLAS上实现的,我的ATLAS副本是隐式线程的),或者您可以阅读源代码

但通常情况下,最好的做法是尝试和测试。如果代码使用一个内核的100%和其他内核的0%,请添加手动线程。如果它现在使用100%的一个内核和10%的其他内核,并且运行速度几乎没有提高,那么将多线程更改为多处理。(幸运的是,Python使这变得非常容易,特别是如果您使用
concurrent.futures
中的Executor类或
multiprocessing
中的Pool类。但是您仍然需要经常考虑一下,如果您有大型数组,那么测试共享与传递的相对成本。)

此外,正如kwatford指出的,仅仅因为某些方法似乎不是隐式并行的,并不意味着它在下一版本的numpy或下一版本的