亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Numpy 向量化和加速

Numpy 向量化和加速

一只名叫tom的貓 2022-07-12 17:39:56
我發現了一個小代碼片段,它曾經是一個雙 for 循環,我設法通過矢量化將它帶到一個單 for 循環中。這樣做會大大縮短時間,所以我想知道是否可以通過矢量化擺脫第二個 for 循環,以及它是否會提高性能。import numpy as npfrom timeit import default_timer as timernlin, npix = 478, 480bb = np.random.rand(nlin,npix)slope = -8fac = 4offset= 0barray = np.zeros([2,2259]);timex = timer()for y in range(nlin):    for x in range(npix):        ling=(np.ceil((x-y/slope)*fac)+1-offset).astype(np.int);        barray[0,ling] +=1;        barray[1,ling] +=bb[y,x];newVar = np.copy(barray)print(timer() - timex)因此,可以通過創建以下矩陣將 ling 從循環中取出lingMat = (np.ceil((np.vstack(npixrange)-nlinrange/slope)*fac)+1-offset).astype(np.int);滿足 lingMat[x,y] = "ling in the for loop at x and y"。這給出了矢量化的第一步。
查看完整描述

1 回答

?
呼啦一陣風

TA貢獻1802條經驗 獲得超6個贊

在矢量化方面,您可能會使用基于np.add.at的東西:


def yaco_addat(bb,slope,fac,offset):

    barray = np.zeros((2,2259),dtype=np.float64)

    nlin_range = np.arange(nlin)

    npix_range = np.arange(npix)

    ling_mat = (np.ceil((npix_range-nlin_range[:,None]/slope)*fac)+1-offset).astype(np.int)  

    np.add.at(barray[0,:],ling_mat,1)

    np.add.at(barray[1,:],ling_mat,bb) 

    return barray

但是,我建議您直接使用numba進行優化,使用@jit帶有 option 的裝飾器nopython=True,它可以為您提供:


import numpy as np

from numba import jit


nlin, npix = 478, 480

bb = np.random.rand(nlin,npix)

slope = -8

fac = 4

offset= 0


def yaco_plain(bb,slope,fac,offset):

    barray = np.zeros((2,2259),dtype=np.float64)

    for y in range(nlin):

        for x in range(npix):

            ling=(np.ceil((x-y/slope)*fac)+1-offset).astype(np.int)

            barray[0,ling] += 1

            barray[1,ling] += bb[y,x]

    return barray


@jit(nopython=True)

def yaco_numba(bb,slope,fac,offset):

    barray = np.zeros((2,2259),dtype=np.float64)

    for y in range(nlin):

        for x in range(npix):

            ling = int((np.ceil((x-y/slope)*fac)+1-offset))

            barray[0,ling] += 1

            barray[1,ling] += bb[y,x]    

    return barray

讓我們檢查一下輸出


np.allclose(yaco_plain(bb,slope,fac,offset),yaco_addat(bb,slope,fac,offset))

>>> True

np.allclose(yaco_plain(bb,slope,fac,offset),yaco_jit(bb,slope,fac,offset))

>>> True

現在是時候了


%timeit yaco_plain(bb,slope,fac,offset)

>>> 648 ms ± 4.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


%timeit yaco_addat(bb,slope,fac,offset)

>>> 27.2 ms ± 92.3 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)


%timeit yaco_jit(bb,slope,fac,offset)

>>> 505 μs ± 995 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

產生一個優化的函數,它比最初的 2 個循環版本53x快得多,也比第np.add.at一個版本快。希望這可以幫助。


查看完整回答
反對 回復 2022-07-12
  • 1 回答
  • 0 關注
  • 129 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號