簡體   English   中英

你可以 GPU 加速 python 中的簡單數學方程,例如:y = 1/x,你是怎么做的?

[英]Can you GPU accelerate a simple math equation in python such as: y = 1/x and how do you do it?

我可以使用我的 GPU 中的內核來加速這個問題並加速它嗎? 如果是這樣,我該怎么做? 在我的 CPU 中大約 10 萬億個單線程無法做到這一點,這就是為什么我想用我的 GPU 來加速它。 我也有興趣看到任何多線程 CPU 的答案,但我真的很想看到它在 GPU 上完成。 理想情況下,我希望答案盡可能簡單。

我的代碼:

y=0

for x in range(1, 10000000000):
    y += 1/x

print(y)

是的,這個操作可以在一個 GPU 上使用基本的並行縮減來完成。 事實上,它非常適合 GPU,因為它主要是令人尷尬的並行,並且大量使用浮點/整數運算。

請注意,這種基本序列的收斂在分析上是眾所周知的 AFAIK(正如@jfaccioni 所指出的那樣),因此您應該更喜歡通常計算成本低得多的分析解決方案。 另請注意,客戶端 GPU 不能很好地有效計算 64 位浮點 (FP) 數,因此您通常應該使用 32 位的,以便以較低的精度為代價來提高速度。 話雖如此,服務器端 GPU 可以有效地計算 64 位 FP 數,因此最佳解決方案取決於您實際擁有的硬件。

Nvidia GPU 通常使用 CUDA 進行編程,與基本的純 Python 代碼相比,它的級別相當低。 有 Python 包裝器和更高級別的庫,但在這種情況下大多數效率不高,因為它們會導致不必要的內存加載/存儲或其他開銷。 AFAIK、PyCUDA 和 Numba 可能是目前最好的工具。 如果您的 GPU 不是 Nvidia GPU,那么您可以使用基於 OpenCL 的庫(因為 CUDA 在非 Nvidia GPU 上還沒有得到很好的支持)。

Numba 支持高級縮減,因此可以非常輕松地完成(注意 Numba 在內部使用 CUDA,因此您需要 Nvidia GPU):

from numba import cuda

# "out" is an array with 1 FP item that must be initialized to 0.0
@cuda.jit
def vec_add(out):
    x = cuda.threadIdx.x
    bx = cuda.blockIdx.x
    bdx = cuda.blockDim.x
    i = bx * bdx + x
    if i < 10_000_000_000-1:
        numba.cuda.atomic.add(out, 0, i+1)

這只是 GPU 內核,而不是整個代碼。 有關如何運行它的更多信息,請閱讀文檔 一般來說,需要關心數據傳輸、分配內核依賴、流等。請記住, GPU 很難(有效地)編程 這個內核很簡單,但顯然不是最優的,尤其是在沒有硬件原子加速單元的舊 GPU 上。 要編寫更快的內核,您需要使用內部循環執行局部歸約。 另請注意,C++ 更適合編寫高效的內核代碼,尤其是使用支持迭代器和高級靈活高效原語的庫(基於 CUDA)時。


請注意,Numba 也可用於實現快速並行 CPU 代碼。 這是一個例子:

import numba as nb

@nb.njit('float64(int64)', fastmath=True, parallel=True)
def compute(limit):
    y = 0.0
    for x in nb.prange(1, limit):
        y += 1 / x
    return y

print(compute(10000000000))

在我的 10 核 CPU 機器上只需要 0.6 秒 CPU 代碼的優點是更簡單、更易於維護、更便攜和更靈活,盡管速度可能更慢。

(Nvidia CUDA) GPU 可以與安裝的適當模塊一起使用。 然而,一個標准的多處理解決方案(不是多線程,因為這是一個僅計算任務)很容易實現,並且相當有效:

import multiprocessing as mp

def inv_sum(start):
  return sum(1/x for x in range(start,start+1000000))

def main():
  pool = mp.Pool(mp.cpu_count())
  result = sum(pool.map(inv_sum, range(1,1000000000,1000000)))
  print(result)

if __name__ == "__main__":
  main()

我不敢在 1萬億上測試運行它,但在我的 8 核 i-5 筆記本電腦上運行10 億只需要大約 20 秒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM