日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python的for循环累加_在python中将6 for循环累计和矢量化

發布時間:2024/9/19 python 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的for循环累加_在python中将6 for循环累计和矢量化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

編輯3:

最后(我認為)版本,有一點更干凈,更快地融入來自max9111's answer的思想。在import numpy as np

from numba import as nb

@nb.njit()

def func1_jit(a, b, c, d):

# Precompute

exp_min = 5 - (a + b + c + d)

exp_max = b

exp = 2. ** np.arange(exp_min, exp_max + 1)

fact_e = np.empty((a + b - 2))

fact_e[0] = 1

for ei in range(1, len(fact_e)):

fact_e[ei] = ei * fact_e[ei - 1]

# Loops

B = 0

for ai in range(0, a):

for bi in range(0, b):

for ci in range(0, c):

for di in range(0, d):

for ei in range(0, ai + bi):

for fi in range(0, ci + di):

B += exp[ei - fi - ai - ci - di + 1 - exp_min] * (ei * ei - 2 * (ei * fi) - 7 * di) * fact_e[ei]

return B

這已經比以前的任何選項都快,但是我們仍然沒有利用多個cpu。一種方法是在函數本身內部完成,例如并行化外部循環。這會在創建線程的每個調用上增加一些開銷,因此對于較小的輸入,實際上會稍慢一點,但對于較大的值,應該會快得多:

^{pr2}$

或者,如果你有很多需要計算函數的點,你也可以在這個級別上并行化。這里a_arr、b_arr、c_arr和{}是要計算函數的值向量:from numba import as nb

@nb.njit(parallel=True)

def func1_arr(a_arr, b_arr, c_arr, d_arr):

B_arr = np.empty((len(a_arr),))

for i in nb.prange(len(B_arr)):

B_arr[i] = func1_jit(a_arr[i], b_arr[i], c_arr[i], d_arr[i])

return B_arr

最佳配置取決于您的輸入、使用模式、硬件等,因此您可以結合不同的想法來適合您的情況。在

編輯2:

其實,忘了我之前說過的話。最好的辦法是JIT編譯算法,但要以更有效的方式進行。首先計算昂貴的部分(我取指數和階乘),然后將其傳遞給編譯的loopy函數:import numpy as np

from numba import njit

def func1(a, b, c, d):

exp_min = 5 - (a + b + c + d)

exp_max = b

exp = 2. ** np.arange(exp_min, exp_max + 1)

ee = np.arange(a + b - 2)

fact_e = scipy.special.factorial(ee)

return func1_inner(a, b, c, d, exp_min, exp, fact_e)

@njit()

def func1_inner(a, b, c, d, exp_min, exp, fact_e):

B = 0

for ai in range(0, a):

for bi in range(0, b):

for ci in range(0, c):

for di in range(0, d):

for ei in range(0, ai + bi):

for fi in range(0, ci + di):

B += exp[ei - fi - ai - ci - di + 1 - exp_min] * (ei * ei - 2 * (ei * fi) - 7 * di) * fact_e[ei]

return B

在我的實驗中,這是迄今為止最快的選擇,并且占用很少的額外內存(只有預計算的值,輸入的大小是線性的)。在a, b, c, d = 4, 6, 3, 4

# The original function

%timeit func1_orig(a, b, c, d)

# 2.07 ms ± 33.7 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# The grid-evaluated function

%timeit func1_grid(a, b, c, d)

# 256 μs ± 25 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

# The precompuation + JIT-compiled function

%timeit func1_jit(a, b, c, d)

# 19.6 μs ± 3.25 μs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

好吧,總有一個選項可以用網格來評估整個事情:import numpy as np

import scipy.special

def func1(a, b, c, d):

ai, bi, ci, di, ei, fi = np.ogrid[:a, :b, :c, :d, :a + b - 2, :c + d - 2]

# Compute

B = (2.) ** (ei - fi - ai - ci - di + 1) * (ei ** 2 - 2 * (ei * fi) - 7 * di) * scipy.special.factorial(ei)

# Mask out of range elements for last two inner loops

m = (ei < ai + bi) & (fi < ci + di)

return np.sum(B * m)

print(func1(4, 6, 3, 4))

# 21769947.844726562

我使用^{}是因為顯然^{}由于某種原因不能與數組一起工作。在

顯然,隨著參數的增加,這種方法的內存開銷將迅速增長。代碼實際執行的計算比需要的多,因為兩個內部循環的迭代次數不同,所以(在這種方法中)必須使用最大的,然后刪除不需要的。希望矢量化可以彌補這一點。一個小的IPython基準測試:a, b, c, d = 4, 6, 3, 4

# func1_orig is the original loop-based version

%timeit func1_orig(a, b, c, d)

# 2.9 ms ± 110 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# func1 here is the vectorized version

%timeit func1(a, b, c, d)

# 210 μs ± 6.34 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

編輯:

注意,前面的方法也不是全有或全無。可以選擇僅對部分循環進行柵格求值。例如,最里面的兩個循環可以這樣矢量化:def func1(a, b, c, d):

B = 0

e = np.arange(a + b - 2).reshape((-1, 1))

f = np.arange(c + d - 2)

for ai in range(0, a):

for bi in range(0, b):

ei = e[:ai + bi]

for ci in range(0, c):

for di in range(0, d):

fi = f[:ci + di]

B += np.sum((2.) ** (ei - fi - ai - ci - di + 1) * (ei ** 2 - 2 * (ei * fi) - 7 * di) * scipy.special.factorial(ei))

return B

這仍然有循環,但它確實避免了額外的計算,并且內存需求要低得多。哪一個最好取決于輸入的大小。在我的測試中,對于原始值(4,6,3,4),這甚至比原始函數慢;而且,對于這種情況,在每個循環上為ei和{}創建新數組要比在預先創建的循環中的一個切片上操作快。但是,如果將輸入乘以4(14,24,12,16),那么這將比原始的(大約x5)快得多,盡管仍然比完全矢量化的(大約x3)慢。另一方面,我可以用這個(大約5分鐘)來計算按10(40,60,30,40)縮放的輸入值,但由于內存的原因(我沒有測試原始函數所需的時間)。使用@numba.jit有點幫助,盡管不是很大(由于階乘函數,不能使用nopython)。您可以嘗試根據輸入的大小對更多或更少的循環進行矢量化。在

總結

以上是生活随笔為你收集整理的python的for循环累加_在python中将6 for循环累计和矢量化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。