下面的代码编译得很好。但是当我尝试运行它时,我得到了
GPUassert: invalid device symbol file.cu 114
当我评论由(!!!)标记的行时,错误不会出现。我的问题是导致这个错误的原因是因为它没有任何意义。
使用nvcc file.cu -arch compute_11
进行编译#include "stdio.h"
#include <algorithm>
#include <ctime>
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
#define THREADS 64
#define BLOCKS 256
#define _dif (((1ll<<32)-121)/(THREADS*BLOCKS)+1)
#define HASH_SIZE 1024
#define ROUNDS 16
#define HASH_ROW (HASH_SIZE/ROUNDS)+(HASH_SIZE%ROUNDS==0?0:1)
#define HASH_COL 1000000000/HASH_SIZE
typedef unsigned long long ull;
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
//fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
printf("GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__device__ unsigned int primes[1024];
//__device__ unsigned char primes[(1<<28)+1];
__device__ long long n = 1ll<<32;
__device__ ull dev_base;
__device__ unsigned int dev_hash;
__device__ unsigned int dev_index;
time_t curtime;
__device__ int hashh(long long x) {
return (x>>1)%1024;
}
// compute (x^e)%n
__device__ ull mulmod(ull x,ull e,ull n) {
ull ans = 1;
while(e>0) {
if(e&1) ans = (ans*x)%n;
x = (x*x)%n;
e>>=1;
}
return ans;
}
// determine whether n is strong probable prime base a or not.
// n is ODD
__device__ int is_SPRP(ull a,ull n) {
int d=0;
ull t = n-1;
while(t%2==0) {
++d;
t>>=1;
}
ull x = mulmod(a,t,n);
if(x==1) return 1;
for(int i=0;i<d;++i) {
if(x==n-1) return 1;
x=(x*x)%n;
}
return 0;
}
__device__ int prime(long long x) {
//unsigned long long b = 2;
//return is_SPRP(b,(unsigned long long)x);
return is_SPRP((unsigned long long)primes[(((long long)0xAFF7B4*x)>>7)%1024],(unsigned long long)x);
}
__global__ void find(unsigned int *out,unsigned int *c) {
unsigned int buff[HASH_ROW][256];
int local_c[HASH_ROW];
for(int i=0;i<HASH_ROW;++i) local_c[i]=0;
long long b = 121+(threadIdx.x+blockIdx.x*blockDim.x)*_dif;
long long e = b+_dif;
if(b%2==0) ++b;
for(long long i=b;i<e && i<n;i+=2) {
if(i%3==0 || i%5==0 || i%7==0) continue;
int hash_num = hashh(i)-(dev_hash*(HASH_ROW));
if(0<=hash_num && hash_num<HASH_ROW) {
if(prime(i)) continue;
buff[hash_num][local_c[hash_num]++]=(unsigned int)i;
if(local_c[hash_num]==256) {
int start = atomicAdd(c+hash_num,local_c[hash_num]);
if(start+local_c[hash_num]>=HASH_COL) return;
unsigned int *out_offset = out+hash_num*(HASH_COL)*4;
for(int i=0;i<local_c[hash_num];++i) out_offset[i+start]=buff[hash_num][i]; //(!!!)
local_c[hash_num]=0;
}
}
}
for(int i=0;i<HASH_ROW;++i) {
int start = atomicAdd(c+i,local_c[i]);
if(start+local_c[i]>=HASH_COL) return;
unsigned int *out_offset = out+i*(HASH_COL)*4;
for(int j=0;j<local_c[i];++j) out_offset[j+start]=buff[i][j]; //(!!!)
}
}
int main(void) {
printf("HASH_ROW: %d\nHASH_COL: %d\nPRODUCT: %d\n",(int)HASH_ROW,(int)HASH_COL,(int)(HASH_ROW)*(HASH_COL));
ull *base_adr;
gpuErrchk(cudaGetSymbolAddress((void**)&base_adr,dev_base));
gpuErrchk(cudaMemset(base_adr,0,7));
gpuErrchk(cudaMemset(base_adr,0x02,1));
}
答案 0 :(得分:7)
一个相当不寻常的错误。
失败的原因是:
-arch compute_11
),您可以将PTX编译步骤推迟到运行时(即您强制执行JIT编译)cudaGetSymbolAddress
上的操作dev_base
失败,并引发错误。为什么JIT编译失败?您可以通过指定ptxas
而不是-arch=sm_11
来触发机器代码编译(运行-arch compute_11
汇编程序)来查找自己。如果你这样做,你将得到这个结果:
ptxas error : Entry function '_Z4findPjS_' uses too much local data (0x10100 bytes, 0x4000 max)
因此,即使您的代码没有调用find
内核,它也必须成功编译才能拥有符号的理智设备环境。
为什么会出现编译错误?因为每个线程请求过多的本地内存。 cc 1.x devices are limited to 16KB local memory per thread,并且您的find
内核要求的内容远远超过({超过64KB)。
当我最初在我的设备上尝试时,我使用的是具有更高限制(每个线程512KB)的cc2.0设备,因此JIT编译步骤成功。
一般来说,我建议同时指定虚拟架构和机器架构,这样做的简便方法是:
nvcc -arch=sm_11 ....
(对于cc1.1设备)
这个question/answer也可能是有意义的,nvcc manual有关于虚拟机与机器架构的更多细节,以及如何为每个架构指定编译阶段。
我相信当您在内核中注释掉那些特定行时错误消失的原因是,在注释掉这些行的情况下,编译器能够优化对这些本地内存区域的访问,并优化掉实例化本地内存。这允许JIT编译步骤成功完成,并且您的代码运行&#34;没有运行时错误&#34;。
您可以通过评论这些行来验证这一点,然后指定完整的编译(nvcc -arch=sm_11 ...
),其中-arch
是--gpu-architecture
的缩写。
答案 1 :(得分:0)
此错误通常意味着内核已针对错误的体系结构进行了编译。您需要find out what the compute capability of your GPU is,然后为该架构编译它。例如。如果您的GPU具有计算能力1.1,请使用-arch = sm_11进行编译。您还可以为多个体系结构构建可执行文件。