Python调用CUDA动态库无法获取正确结果的问题求助
CUDA与Python交互返回全0问题的修复方案
我在Python中调用CUDA生成的DLL时无法获取正确结果,但CUDA脚本单独测试能返回正确结果:
- CU端正确输出:
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] - Python端错误输出:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
核心错误点及修复
1. C++函数中输出指针赋值错误
原代码中out = C;仅修改了函数形参的指针指向,并未将计算结果复制到Python传入的内存缓冲区。需替换为内存复制操作:
// 替换原有的 out = C; memcpy(out, C, sizeof(double) * 24); // 24为输出数组固定长度
2. CUDA内存释放错误
原代码中cudaFree(cellbox);释放的是栈上数组,而非cudaMalloc分配的设备内存cellbox_d,会导致未定义行为,修正为:
cudaFree(cellbox_d); // 替换 cudaFree(cellbox);
3. 缺少CUDA同步与错误检查
Kernel启动后需等待执行完成,且应检查所有CUDA操作的错误,避免隐性失败:
- 添加错误检查宏(放在代码开头):
#define CHECK_CUDA_ERROR(err) \ if (err != cudaSuccess) { \ fprintf(stderr, "CUDA error at %s:%d: %s\n", __FILE__, __LINE__, cudaGetErrorString(err)); \ exit(EXIT_FAILURE); \ }
- 在Kernel调用后添加同步,并为所有CUDA操作添加错误检查:
MatAdd<<<1,blockDim>>>(cellbox_d, verticess_d, C_d, halfcells_d , rows, cols); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); // 等待Kernel执行完成
4. Python端参数错误
原代码中sv = np.array(cellboxsize).astype('double')错误地将cellbox的大小赋值给verticess的大小参数,修正为:
sv = np.array(verticesssize).astype('double')
修正后的完整代码
修正后的CUDA代码
#include <stdio.h> #include <stdlib.h> #include <vector> #include<iostream> #include <cstring> using namespace std; #define CHECK_CUDA_ERROR(err) \ if (err != cudaSuccess) { \ fprintf(stderr, "CUDA error at %s:%d: %s\n", __FILE__, __LINE__, cudaGetErrorString(err)); \ exit(EXIT_FAILURE); \ } #define DELLEXPORT extern "C" __declspec(dllexport) __global__ void MatAdd(const double *cellbox, const double *verticess, double *C, const double *halfcells,int rows, int cols) { int cellboxidy = threadIdx.y; int verticessidx = threadIdx.x; const double mincell [3] = {cellbox[cellboxidy * 3] - halfcells[0], cellbox[cellboxidy * 3 + 1] - halfcells[1], cellbox[cellboxidy * 3 + 2] - halfcells[2]}; const double maxcell [3] = {cellbox[cellboxidy * 3] + halfcells[0], cellbox[cellboxidy * 3 + 1] + halfcells[1], cellbox[cellboxidy * 3 + 2] + halfcells[2]}; if (verticess[verticessidx * 3] >= mincell[0] && verticess[verticessidx * 3] <= maxcell[0] && verticess[verticessidx * 3 + 1] >= mincell[1] && verticess[verticessidx * 3 + 1] <= maxcell[1] && verticess[verticessidx * 3 + 2] >= mincell[2] && verticess[verticessidx * 3 + 2] <= maxcell[2]){ C[cellboxidy * 3] = 1; C[cellboxidy * 3 + 1] = 1; C[cellboxidy * 3 + 2] = 1; } } DELLEXPORT void twodarray(double *out , double *celb ,double *ve , double *hfc , double *sizecellbox , double *sizeverticess) { double cellbox [24] = {0}; for(int i = 0 ; i<int(*sizecellbox) ; i++){ cellbox[(i*3)] = celb[(i*3)]; cellbox[(i*3) + 1] = celb[(i*3) + 1]; cellbox[(i*3) + 2] = celb[(i*3) + 2]; } double verticess [24] = {0}; for(int i = 0 ; i<int(*sizeverticess) ; i++){ verticess[(i*3)] = ve[(i*3)]; verticess[(i*3) + 1] = ve[(i*3) + 1]; verticess[(i*3) + 2] = ve[(i*3) + 2]; } const int N = *sizecellbox; int M = *sizeverticess; double halfcells[3] = {}; halfcells[0] = hfc[0]; halfcells[1] = hfc[1]; halfcells[2] = hfc[2]; double *C; double *cellbox_d = 0, *verticess_d = 0 , *halfcells_d = 0 , *C_d = 0; int rows = N; int cols = M; dim3 blockDim(*sizecellbox, *sizeverticess); C = (double *)malloc(sizeof(*C)*100); CHECK_CUDA_ERROR(cudaMalloc((void**)&C_d, sizeof(*C_d)*100)); CHECK_CUDA_ERROR(cudaMalloc((void**)&cellbox_d, sizeof(*cellbox_d)*100)); CHECK_CUDA_ERROR(cudaMalloc((void**)&verticess_d, sizeof(*verticess_d)*100)); CHECK_CUDA_ERROR(cudaMalloc((void**)&halfcells_d, sizeof(*halfcells_d)*3)); CHECK_CUDA_ERROR(cudaMemcpy(cellbox_d, cellbox, sizeof(*cellbox_d)*100, cudaMemcpyHostToDevice)); CHECK_CUDA_ERROR(cudaMemcpy(verticess_d, verticess, sizeof(*verticess_d)*100, cudaMemcpyHostToDevice)); CHECK_CUDA_ERROR(cudaMemcpy(halfcells_d, halfcells, sizeof(*halfcells_d)*3, cudaMemcpyHostToDevice)); MatAdd<<<1,blockDim>>>(cellbox_d, verticess_d, C_d, halfcells_d , rows, cols); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); CHECK_CUDA_ERROR(cudaMemcpy(C, C_d, sizeof(*C)*100, cudaMemcpyDeviceToHost)); memcpy(out, C, sizeof(double)*24); cudaFree(cellbox_d); cudaFree(verticess_d); cudaFree(C_d); cudaFree(halfcells_d); free(C); } // 编译命令:nvcc -Xcompiler -fPIC -shared -o 2darray3.dll 2darray3.cu
修正后的Python代码
import numpy as np import ctypes from ctypes import * def get_cuda_square(): dll = ctypes.windll.LoadLibrary("C:\\Users\\Ali\\Desktop\\test9\\cuda_remember\\with link python\\2darray3.dll") func = dll.twodarray func.argtypes = [POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double),POINTER(c_double) , POINTER(c_double)] return func __cuda_square = get_cuda_square() size = int(24) cellbox_array = [[-0.35263609886169434, -0.35263609886169434, -0.35263609886169434] , [0.35263609886169434, -0.35263609886169434, -0.35263609886169434] , [-0.35263609886169434, 0.35263609886169434, -0.35263609886169434] , [0.35263609886169434, 0.35263609886169434, -0.35263609886169434],[-0.35263609886169434, -0.35263609886169434, 0.35263609886169434] , [0.35263609886169434, -0.35263609886169434, 0.35263609886169434],[-0.35263609886169434, 0.35263609886169434, 0.35263609886169434] , [0.35263609886169434, 0.35263609886169434, 0.35263609886169434]] cellboxsize = c_double(len(cellbox_array)) verticess_array = [[0.1, 0.2, 0.3] , [0.4, 0.5, 0.6] ,[0.7, 0.8, 0.9] , [0.10, 0.11, 0.12],[0.13, 0.14, 0.15] , [0.16, 0.17, 0.18],[0.19, 0.20, 0.21] , [0.22, 0.23, 0.24]] verticesssize = c_double(len(verticess_array)) hfc_array = [1.7546,1.4456,1.4545544] cellbox = np.array(cellbox_array).astype('double') verticess = np.array(verticess_array).astype('double') hfc = np.array(hfc_array).astype('double') sc = np.array(cellboxsize).astype('double') sv = np.array(verticesssize).astype('double') output = np.zeros(size).astype('double') a_p = output.ctypes.data_as(POINTER(c_double)) c_p = cellbox.ctypes.data_as(POINTER(c_double)) v_p = verticess.ctypes.data_as(POINTER(c_double)) h_p = hfc.ctypes.data_as(POINTER(c_double)) sc_p = sc.ctypes.data_as(POINTER(c_double)) sv_p = sv.ctypes.data_as(POINTER(c_double)) __cuda_square(a_p, c_p, v_p , h_p,sc_p , sv_p) print(output)
内容的提问来源于stack exchange,提问作者user5963087
相关产品推荐
相关产品推荐

