如何加速scipy.weave中的多维数组访问?

2 投票
4 回答
1760 浏览
提问于 2025-04-16 01:49

我正在把我的C代码嵌入到Python中,以加快循环的速度:

from scipy import weave
from numpy import *

#1) create the array
a=zeros((200,300,400),int)
for i in range(200):
    for j in range(300):
        for k in range(400):    
            a[i,j,k]=i*300*400+j*400+k
#2) test on c code to access the array
code="""
for(int i=0;i<200;++i){
for(int j=0;j<300;++j){
for(int k=0;k<400;++k){
printf("%ld,",a[i*300*400+j*400+k]);    
}
printf("\\n");
}
printf("\\n\\n");
}
"""
test =weave.inline(code, ['a'])

这工作得很好,但当数组很大的时候,还是挺耗费资源的。有人建议我用.a.strides,而不是那种复杂的“a[i*300*400+j*400+k]”这种写法。我对.strides的文档看不太懂。

有没有什么建议?

提前谢谢你们!

4 个回答

0

在C语言中,没有办法加快访问多维数组的速度。你必须先计算出数组的索引,然后再去获取它的值,这个过程就是这么简单。

1

问题在于,你的C代码正在把240万个数字打印到屏幕上。这当然会花费一些时间,因为这些数字需要先转换成字符串,然后再显示出来。你真的需要把所有数字都打印到屏幕上吗?你的最终目标是什么呢?

为了做个对比,我尝试把另一个数组设置为a中的每个元素。这个过程大约花了0.05秒。而我在尝试打印所有元素到屏幕上时,过了大约30秒就放弃了计时。

4

你可以用下面的代码替换掉这三个for循环:

grid=np.ogrid[0:200,0:300,0:400]
a=grid[0]*300*400+grid[1]*400+grid[2]

根据下面的内容,这样做可能会让速度提高大约68倍(或者更快?见下文):

% python -mtimeit -s"import test" "test.m1()"
100 loops, best of 3: 17.5 msec per loop
% python -mtimeit -s"import test" "test.m2()"
1000 loops, best of 3: 247 usec per loop

这是一个测试文件:test.py:

import numpy as np

n1,n2,n3=20,30,40
def m1():
    a=np.zeros((n1,n2,n3),int)
    for i in range(n1):
        for j in range(n2):
            for k in range(n3):    
                a[i,j,k]=i*300*400+j*400+k
    return a

def m2():    
    grid=np.ogrid[0:n1,0:n2,0:n3]
    b=grid[0]*300*400+grid[1]*400+grid[2]
    return b 

if __name__=='__main__':
    assert(np.all(m1()==m2()))

当n1、n2、n3分别设置为200、300、400时,

python -mtimeit -s"import test" "test.m2()"

在我的电脑上运行了182毫秒,

python -mtimeit -s"import test" "test.m1()"

而且还没有完成。

撰写回答