【发布时间】:2015-01-21 13:28:49
【问题描述】:
我正在尝试从设备运行矩阵求逆。如果从主机调用,此逻辑可以正常工作。
编译行如下(Linux):
nvcc -ccbin g++ -arch=sm_35 -rdc=true simple-inv.cu -o simple-inv -lcublas_device -lcudadevrt
我收到以下似乎无法解决的警告。 (我的 GPU 是 Kepler。我不知道它为什么要尝试链接到 Maxwell 例程。我有 Cuda 6.5-14):
nvlink warning : SM Arch ('sm_35') not found in '/usr/local/cuda/bin/../targets/x86_64-linux/lib/libcublas_device.a:maxwell_sm50_sgemm.o'
程序运行:
handle 0 n = 3
simple-inv.cu:63 Error [an illegal memory access was encountered]
测试程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cuda_runtime.h>
#include <cublas_v2.h>
#define PERR(call) \
if (call) {\
fprintf(stderr, "%s:%d Error [%s] on "#call"\n", __FILE__, __LINE__,\
cudaGetErrorString(cudaGetLastError()));\
exit(1);\
}
#define ERRCHECK \
if (cudaPeekAtLastError()) { \
fprintf(stderr, "%s:%d Error [%s]\n", __FILE__, __LINE__,\
cudaGetErrorString(cudaGetLastError()));\
exit(1);\
}
__global__ void
inv_kernel(float *a_i, float *c_o, int n)
{
int p[3], info[1], batch;
cublasHandle_t hdl;
cublasStatus_t status = cublasCreate_v2(&hdl);
printf("handle %d n = %d\n", status, n);
info[0] = 0;
batch = 1;
float *a[] = {a_i};
const float *aconst[] = {a_i};
float *c[] = {c_o};
// See
// http://docs.nvidia.com/cuda/pdf/CUDA_Dynamic_Parallelism_Programming_Guide.pdf
//http://stackoverflow.com/questions/27094612/cublas-matrix-inversion-from-device
status = cublasSgetrfBatched(hdl, n, a, n, p, info, batch);
__syncthreads();
printf("rf %d info %d\n", status, info[0]);
status = cublasSgetriBatched(hdl, n, aconst, n, p,
c, n, info, batch);
__syncthreads();
printf("ri %d info %d\n", status, info[0]);
cublasDestroy_v2(hdl);
printf("done\n");
}
static void
run_inv(float *in, float *out, int n)
{
float *a_d, *c_d;
PERR(cudaMalloc(&a_d, n*n*sizeof(float)));
PERR(cudaMalloc(&c_d, n*n*sizeof(float)));
PERR(cudaMemcpy(a_d, in, n*n*sizeof(float), cudaMemcpyHostToDevice));
inv_kernel<<<1, 1>>>(a_d, c_d, n);
cudaDeviceSynchronize();
ERRCHECK;
PERR(cudaMemcpy(out, c_d, n*n*sizeof(float), cudaMemcpyDeviceToHost));
PERR(cudaFree(a_d));
PERR(cudaFree(c_d));
}
int
main(int argc, char **argv)
{
float c[9];
float a[] = {
1, 2, 3,
0, 4, 5,
1, 0, 6 };
run_inv(a, c, 3);
return 0;
}
我已按照http://docs.nvidia.com/cuda/cublas/index.html#device-api 第 2.1.9 节的指南进行操作,但我怀疑我忽略了一些东西。
注意:于 11/24 编辑以使用正确的指针输入。这仍然会报告内核内部的非法内存访问。
【问题讨论】:
-
您发布的代码中的第 63 行是空格。代码中发生的错误究竟在哪里?
-
设备同步期间的第 64 行。我必须发布和较旧的输出。我怀疑在调用 cublasSgetrfBatched 期间。
-
(float**)a_i看起来很可疑。你的意思是传递a_i的地址而不是它的值吗? -
@VAndrei:是的,这是可能的,您的评论与问题完全无关。
-
@Bob:你链接的代码和你的代码不一样,区别在于你有一个非法的演员表。
*a[] = {a_i}; cublasSgetrfBatched(..., a, ....)和cublasSgetrfBatched(..., (float**)a_i, ...)不是等价的,如果你认为是,那你需要修改C++中的指针理论。