【问题标题】:Python array sum vs MATLABPython数组总和与MATLAB
【发布时间】:2014-05-16 20:25:04
【问题描述】:

我正在慢慢切换到 Python,我想做一个简单的测试来比较简单数组求和的性能。我生成一个随机的 1000x1000 数组,并将该数组中的每个值加一。

这是我的 Python 脚本:

import time

import numpy
from numpy.random import random

def testAddOne(data):
    """
    Test addOne
    """
    return data + 1

i = 1000
data = random((i,i))
start = time.clock()
for x in xrange(1000): 
    testAddOne(data)

stop = time.clock()
print stop - start

还有我在 MATLAB 中的函数:

function test
%parameter declaration
c=rand(1000);

tic
for t = 1:1000
    testAddOne(c);
end
fprintf('Structure: \n')
toc
end

function testAddOne(c)
c = c + 1;
end

Python 需要 2.77 - 2.79 秒,与 MATLAB 函数相同(实际上我对 Numpy 印象深刻!)。我必须对我的 Python 脚本进行哪些更改才能使用多线程?因为我没有工具箱,所以我不能在 MATLAB 中。

【问题讨论】:

  • MATLAB 上真的公平吗?一次添加一个元素,你可以一口气完成,因为这就是 MATLAB 的强大之处?如果您使用inline 功能,如果您使用MATLAB 获得一些明显的改进,我不会感到惊讶。
  • @Divakar 您应该再次检查代码,MATLAB 正在一次调用中添加这些代码。可能误导你的是我运行了 1000 次,这也对应于数组的长度。为了理解,for循环t = 1:1000可以是t = 1:randi([1000,2000])
  • 没错,这就是为什么我的函数使用 MATLAB 向量化方法的原因。如果我不这样做,我将不得不使用两个 for 循环语句 i 和 j 并遍历每个索引以添加一个。就像你说的那样,不会使用 MATLAB 的强大功能。
  • 看起来比较公平。
  • 一些相关讨论hereherehere

标签: python arrays multithreading matlab numpy


【解决方案1】:

Python 中的多线程 仅在线程被阻塞的情况下有用,例如在获取输入时,这里不是这种情况(有关更多详细信息,请参阅this question 的答案)。然而,多处理 在 Python 中很容易做到。多处理一般在here 中涵盖。

下面是采用与您的示例类似的方法的程序

import time
import numpy
from numpy.random import random
from multiprocessing import Process

def testAddOne(data):
    return data + 1

def testAddN(data,N):
    # print "testAddN", N
    for x in xrange(N): 
        testAddOne(data)

if __name__ == '__main__':
    matrix_size = 1000
    num_adds = 10000
    num_processes = 4

    data = random((matrix_size,matrix_size))

    start = time.clock()
    if num_processes > 1:
        processes = [Process(target=testAddN, args=(data,num_adds/num_processes))
                     for i in range(num_processes)]
        for p in processes:
            p.start()
        for p in processes:
            p.join()
    else:
        testAddN(data,num_adds)

    stop = time.clock()
    print "Elapsed", stop - start

下面是一个更有用的示例,使用pool of worker processes 连续将1 加到不同的矩阵中。

import time
import numpy
from numpy.random import random
from multiprocessing import Pool

def testAddOne(data):
    return data + 1

def testAddN(dataN):
    data,N=dataN
    for x in xrange(N): 
        data = testAddOne(data)
    return data

if __name__ == '__main__':
    num_matrices = 4
    matrix_size = 1000
    num_adds_per_matrix = 2500

    num_processes = 4

    inputs = [(random((matrix_size,matrix_size)), num_adds_per_matrix)
              for i in range(num_matrices)]
    #print inputs # test using, e.g., matrix_size = 2

    start = time.clock()

    if num_processes > 1:
        proc_pool = Pool(processes=num_processes)
        outputs = proc_pool.map(testAddN, inputs)    
    else:
        outputs = map(testAddN, inputs)

    stop = time.clock()
    #print outputs # test using, e.g., matrix_size = 2
    print "Elapsed", stop - start

在这种情况下,testAddN 中的代码实际上对调用testAddOne 的结果做了一些事情。您可以取消注释打印语句以检查是否正在完成一些有用的工作。

在这两种情况下,我都将添加的总数更改为 10000;添加更少,启动流程的成本变得更加重要(但您可以尝试使用这些参数)。你也可以尝试num_processes。在我的机器上,我发现与使用num_processes=1 在同一进程中运行相比,使用num_processes=4 生成四个进程的速度快了两倍。

【讨论】:

  • 我现在正在尝试您的第一个示例,我得到了 2.16 倍的加速(有 4 个进程)
  • 仍在尝试理解您在第二个示例中所做的事情!但是感谢这两种解决方案!
  • @m_power 感谢您的反馈!在计算中map用来表示取一个列表L,用某个函数f处理列表中的每个元素,产生另一个列表L'。列表L=[x0, x1, ..., xn] 变为L=[f(x0), f(x1), ..., f(xn)]。我真正喜欢 Python 进程池的地方在于,多进程映射看起来与单进程映射几乎完全相同。
猜你喜欢
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
  • 2022-12-10
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
相关资源
最近更新 更多