Я новичок в cuda и пытаюсь вычислить матрицу с помощью gpu. Идея состоит в том, чтобы использовать индекс потока и индекс блока, чтобы найти разные участки памяти двух разных матриц. Вычислите матрицу поблочно, а затем скопируйте ее обратно в соответствующую выходную матрицу.
Код выглядит примерно так:
import math
import numpy as np
from numba import cuda
@cuda.jit(device=True)
def GPU_SimpleOp(dim1, dim2):
x = dim1 + dim2
return x
@cuda.jit
def GPUCore(nd_matrix1, nd_matrix2, nd_output):
blockix = cuda.blockIdx.x
threadix = cuda.threadIdx.x
if blockix > nd_matrix1.shape[0] or threadix > nd_matrix2.shape[0]:
return
nd_output[blockix, threadix] = GPU_SimpleOp(nd_matrix1[blockix], nd_matrix2[threadix])
def Test(nd_matrix1, nd_matrix2, blockno=256, threadno = 256):
cuda.pinned(nd_matrix1)
cuda.pinned(nd_matrix2)
dim1 = nd_matrix1.shape[0]
dim2 = nd_matrix2.shape[0]
output = np.ndarray(shape=[dim1, dim2])
nd_output = np.ascontiguousarray(output)
cuda.pinned(nd_output)
blocks_dim1 = int(math.ceil(dim1 / blockno))
thread_dim2 = int(math.ceil(dim2 / threadno))
for i in range(blocks_dim1):
dim1_s = i
dim1_e = min((i + 1) * blockno, nd_matrix1.shape[0])
for j in range(thread_dim2):
dim2_s = j
dim2_e = min((j + 1) * threadno, nd_matrix2.shape[0])
stream = cuda.stream()
device_mat1 = cuda.to_device(nd_matrix1[dim1_s:dim1_e], stream)
device_mat2 = cuda.to_device(nd_matrix2[dim2_s:dim2_e], stream)
device_output = cuda.to_device(nd_output[dim1_s:dim1_e, dim2_s:dim2_e], stream)
GPUCore[blockno, threadno, stream](device_mat1, device_mat2, device_output)
device_output.copy_to_host(nd_output[dim1_s:dim1_e, dim2_s:dim2_e], stream)
stream.synchronize()
if __name__ == '__main__':
dim1 = 1000
dim2 = 5000
nd_matrix1 = np.random.random(dim1)
nd_matrix2 = np.random.random(dim2)
blockno = 256
threadno = 256
Test(nd_matrix1, nd_matrix2, blockno, threadno)
Когда я запускаю этот код, я получил сообщение об ошибке:
Connected to pydev debugger (build 201.7846.77)
Traceback (most recent call last):
File "D:\ProgramData\Anaconda3\lib\contextlib.py", line 130, in __exit__
self.gen.throw(type, value, traceback)
File "D:\ProgramData\Anaconda3\lib\site-packages\numba\cuda\cudadrv\devices.py", line 127, in ensure_context
yield
File "D:\ProgramData\Anaconda3\lib\site-packages\numba\cuda\cudadrv\devices.py", line 225, in _require_cuda_context
return fn(*args, **kws)
File "D:\ProgramData\Anaconda3\lib\site-packages\numba\cuda\api.py", line 110, in to_device
to, new = devicearray.auto_device(obj, stream=stream, copy=copy)
File "D:\ProgramData\Anaconda3\lib\site-packages\numba\cuda\cudadrv\devicearray.py", line 692, in auto_device
sentry_contiguous(obj)
File "D:\ProgramData\Anaconda3\lib\site-packages\numba\cuda\cudadrv\devicearray.py", line 666, in sentry_contiguous
raise ValueError(errmsg_contiguous_buffer)
ValueError: Array contains non-contiguous buffer and cannot be transferred as a single memory region. Please ensure contiguous buffer with numpy .ascontiguousarray()
Ошибка кода в строке device_output = cuda.to_device(nd_output[dim1_s:dim1_e, dim2_s:dim2_e], stream)
. Хотя я погуглил ответ и попытался использовать nd_output = np.ascontiguousarray(output)
. Это все еще не работает. Любая помощь, пожалуйста?