【发布时间】:2021-09-17 10:56:45
【问题描述】:
最近几天我刚刚开始使用 Numba 进行 GPU 编程,并且我已经从博客周围的零散信息中学习了一些技术,其中一些在 C programming guide 中,在 Stack 社区中也有很多。
为了简化,我正在尝试提高我的模拟性能,而不是在使用常规Python 代码之前。使用Numba,我已经提高了我的代码的性能,现在在我的 Geforce GTX 1660TI 中运行速度提高了 45 倍,但现在我正试图进一步提高一点,正如 Here 提到的,我的内核没有良好的内存访问模式。
最近我试图了解在某些内核中使用共享内存来提高性能,就像在这个post 中一样,但我不知道这个例子是否对我有帮助,因为据我了解,它具有明显的优势共享内存,在我的常规内核中,我通常使用多个矩阵或向量进行元素乘法。
其实我不知道这是否应该在这里问,所以如果这里不是正确的地方,请原谅我。
我的代码的主要内核之一及其测试实现在下面的代码中
from timeit import default_timer as timer
import numba
from numba import jit, guvectorize, int32, int64, float64, prange
from numba import cuda
import numpy as np
from numpy import *
import math
stream = cuda.stream()
D = 9
nx = 20000
ny = 1000
ly = ny-1
uLB = 0.04
cx = np.array([0, 1,-1, 0, 0, 1,-1, 1,-1],dtype=np.float64);
cy = np.array([0, 0, 0, 1,-1, 1,-1,-1, 1],dtype=np.float64);
c = np.array([cx,cy]);
w = np.array([4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36],dtype=np.float64);
def inivel(d, x, y):
return (1-d) * uLB * (1 + 1e-4*sin(y/ly*2*pi))
@cuda.jit
def equilibrium_gpu(rho,u,c,w,feq):
nx2 = rho.shape[0]
ny2 = rho.shape[1]
cuda.syncthreads()
j, k = cuda.grid(2)
if (j < nx2) & (k < ny2):
for i in range(9):
feq[i, j, k] = rho[j,k]*w[i] * (1 + (3 * (c[0,i]*u[0,j,k] + c[1,i]*u[1,j,k])) + 0.5*(3 * (c[0,i]*u[0,j,k] + c[1,i]*u[1,j,k]))**2 - (3/2 * (u[0,j,k]**2 + u[1,j,k]**2)))
cuda.syncthreads()
vel = fromfunction(inivel, (2,nx,ny))
rho = np.ones([nx, ny], dtype='float64')
res = np.zeros([D, nx, ny], dtype='float64')
feq = np.zeros((9,nx,ny))
rho_device = cuda.to_device(rho, stream=stream)
u_device = cuda.to_device(vel, stream=stream)
c_device = cuda.to_device(c, stream=stream)
w_device = cuda.to_device(w, stream=stream)
feq_device = cuda.device_array(shape=(D,nx,ny,), dtype=np.float64, stream=stream)
threadsperblock = (16, 16)
blockspergrid_x = math.ceil(nx / threadsperblock[0])
blockspergrid_y = math.ceil(ny / threadsperblock[1])
blockspergrid = (blockspergrid_x, blockspergrid_y)
s = timer()
cuda.synchronize()
equilibrium_gpu[blockspergrid, threadsperblock,stream](rho_device,u_device,c_device,w_device,feq_device)
cuda.synchronize()
gpu_time = timer() - s
print(gpu_time)
我想知道如何通过共享内存或其他方式来提高这个内核的性能。
【问题讨论】:
-
明显的性能改进是将内存布局从 [D, nx, ny] 更改为 [nx, ny, D]
-
既然你说,这对我来说也很明显:),谢谢你的建议