【问题标题】:Iterate over two big arrays at once一次迭代两个大数组
【发布时间】:2012-08-10 12:19:42
【问题描述】:

我必须遍历两个 1000x1000 大的数组。我已经将分辨率降低到 100x100 以加快迭代速度,但 ONE 阵列仍然需要大约 15 分钟! 因此,我尝试同时对两者进行迭代,为此我发现了这一点:

for index, (x,y) in ndenumerate(izip(x_array,y_array)):

然后我得到错误:

ValueError: too many values to unpack

这是我的完整 python 代码:我希望你能帮助我加快速度,因为这是我的硕士论文,最后我必须运行它大约 100 次......

area_length=11
d_circle=(area_length-1)/2

xdis_new=xdis.copy()
ydis_new=ydis.copy()
ie,je=xdis_new.shape


while (np.isnan(np.sum(xdis_new))) and (np.isnan(np.sum(ydis_new))):
xdis_interpolated=xdis_new.copy()
ydis_interpolated=ydis_new.copy()
# itx=np.nditer(xdis_new,flags=['multi_index'])
# for x in itx:
    # print 'next x and y'
for index, (x,y) in ndenumerate(izip(xdis_new,ydis_new)):
    if np.isnan(x):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=xdis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            xdis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    if np.isnan(y):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=ydis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            ydis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    else:
        print 'no need to interpolate'

xdis_new=xdis_interpolated
ydis_new=ydis_interpolated

【问题讨论】:

  • 对于那些不知情的人 - izip() 来自 itertools 模块:from itertools import izp

标签: python performance loops


【解决方案1】:

一些建议:

  • 分析您的代码以查看最慢的部分。可能不是迭代,而是每次都需要完成的计算。
  • 尽可能减少函数调用。 Python 中的函数调用不是免费的。
  • 将最慢的部分重写为 C 扩展,然后在 Python 代码中调用该 C 函数(请参阅Extending and Embedding the Python interpreter)。
  • This page 也有一些很好的建议。

【讨论】:

    【解决方案2】:

    评论 #1:您不想在 izip 迭代器上使用 ndenumerate,因为它会输出迭代器,这不是您想要的。

    评论 #2:

    i1=index[0]-(area_length-1)/2
    if i1<0:
        i1=0
    

    可以简化为i1 = min(index[0]-(area_length-1)/2, 0),您可以将(area_length+/-1)/2 存储在特定变量中。

    想法 #1:尝试迭代数组的平面版本,即使用类似的东西

    for (i, (x, y)) in enumerate(izip(xdis_new.flat,ydis_new.flat)): 
    

    您可以通过divmod(i, xdis_new.shape[-1]) 获取原始索引,因为您应该首先按行进行迭代。

    想法 #2:仅在 nans 上进行迭代,即使用 np.isnan(xdis_new)|np.isnan(ydis_new) 索引您的数组,这样可以节省一些迭代

    编辑#1

    • 您可能不需要在循环中初始化 dweight_facweighted_area,因为您分别计算它们。

    • 您的weight[where(d&gt;0)] 可以简化为weight[d&gt;0]

    • 您需要weight_fac 吗?您不能只计算weight 然后将其标准化吗?这应该会为您节省一些临时数组。

    【讨论】:

    • 你的cmets和想法听起来很不错!我已经考虑过展平数组,但是我在获取原始索引时遇到了问题,非常感谢!我会试试你说的,然后我们会看到... =)
    • 我的 divmod 有问题...我把它放在 for 循环之后,但我收到错误:TypeError: unsupported operand type(s) for divmod(): 'tuple'和'int'你能告诉我如何以及在哪里使用这个函数吗?谢谢!
    • 好的,我想我有一个 divmod 函数的答案... [链接] (stackoverflow.com/questions/9482550/…) 它似乎工作...
    • 你可以尝试类似:[(i,j,x,y) for ((i,j),x,y) in zip(zip(*np.unravel_index(np.arange(np.multiply(*X.shape)),X.shape)),X.flat,Y.flat)]
    【解决方案3】:

    您可以将其用作for 循环:

    for index, x in ndenumerate((x_array,y_array)):

    但这对你帮助不大,因为你的电脑不能同时做两件事。

    【讨论】:

      【解决方案4】:

      分析绝对是确定所有时间实际花在哪里的良好开端。

      我通常使用cProfile 模块,因为它需要的开销最小,并且给我提供了足够多的信息。

      import cProfile
      import pstats
      cProfile.run('main()', "ProfileData.txt", 'tottime')
      p = pstats.Stats('ProfileData.txt')   
      p.sort_stats('cumulative').print_stats(100)
      

      在您的示例中,您必须将代码包装到 main() 函数中,才能在文件末尾使用此代码 sn-p。

      【讨论】:

        【解决方案5】:

        您特别要求在一个循环中迭代两个数组。这是一种方法

        l1 = ["abc", "def", "hi"]
        l2 = ["ghi", "jkl", "lst"]
        for f,s in zip(l1,l2):
            print "%s : %s" %(f,s)
        

        以上是python 3,python 2可以使用izip

        【讨论】:

          猜你喜欢
          • 2011-02-17
          • 1970-01-01
          • 2021-10-05
          • 2021-04-25
          • 1970-01-01
          • 2010-11-25
          • 2019-08-24
          • 2021-12-01
          相关资源
          最近更新 更多