【发布时间】:2011-06-15 21:01:32
【问题描述】:
我有这个 c++ 项目,我在其中通过包装函数调用 cuda 内核。
我的 c++ 文件如下所示(这是 extern.cc):
#include "extern.h"
#include "qc/operator.h"
#include "qc/quStates.h"
#include "gpu.h"
...
ROUTINE(ext_bit) {
int i;
quState *qbit;
PAR_QUSTATE(q,"q");
opBit *op;
tComplex I(0,1);
tComplex sg= inv ? -1 : 1;
char c=(def->id())[0];
if(def->id().length()!=1) c='?';
switch(c) {
case 'H': op=new opBit(1,1,1,-1,sqrt(0.5)); break;
case 'X': op=new opBit(0,1,1,0); break;
case 'Y': op=new opBit(0,-I,I,0); break;
case 'Z': op=new opBit(1,0,0,-1); break;
case 'S': op=new opBit(1,0,0,sg*I); break;
case 'T': op=new opBit(1,0,0,sqrt(0.5)+sg*sqrt(0.5)*I); break;
case '?':
default: EXTERR("unknown single qubit operator "+def->id());
}
// This is where I call my wrapper function
// the error that I get is: expected primary-expression before ',' token
gpucaller(opBit, q);
qcl_delete(op);
return 0;
}
其中 "gpucaller" 是我调用内核的包装函数,都在 cuda_kernel.cu 中定义:
/* compiling with:
nvcc -arch sm_11 -c -I"/home/glu/NVIDIA_GPU_Computing_SDK/C/common/inc" -I"." -I"./qc" -I"/usr/local/cuda/include" -o cuda_kernel.o cuda_kernel.cu
*/
#ifndef _CUDA_KERNEL_H_
#define _CUDA_KERNEL_H_
#define MAX_QUBITS 25
#define BLOCKDIM 512
#define MAX_TERMS_PER_BLOCK (2*BLOCKDIM)
#define THREAD_MASK (~0ul << 1)
// includes
#include <cutil_inline.h>
#include "gpu.h"
__constant__ float devOpBit[2][2];
__global__ void qcl1(cuFloatComplex *a, int N, int qbCount, int blockGrpSize, int k)
{
//int idx = blockIdx.x * BLOCKDIM + threadIdx.x;
//int tx = threadIdx.x;
cuFloatComplex t0_0, t0_1, t1_0, t1_1;
int x0_idx, x1_idx;
int i, grpSize, b0_idx, b1_idx;
__shared__ cuFloatComplex aS[MAX_TERMS_PER_BLOCK];
...
}
void gpucaller(opBit* op, quBaseState* q) {
// make an operator copy
float** myOpBit = (float**)op->getDeviceReadyOpBit();
unsigned int timer = 0;
cuFloatComplex *a_d;
long int N = 1 << q->mapbits();
int size = sizeof(cuFloatComplex) * N;
// start timer
cutilCheckError( cutCreateTimer( &timer));
cutilCheckError( cutStartTimer( timer));
// allocate device memory
cudaMalloc((void**)&a_d,size);
// copy host memory to device
cudaMemcpy(a_d, q->termsarray, size, cudaMemcpyHostToDevice);
// copy quantic operator to constant memory
cutilSafeCall( cudaMemcpyToSymbol(devOpBit, myOpBit, 2*sizeof(float[2]), 0) );
printf("Cuda errors: %s\n", cudaGetErrorString( cudaGetLastError() ) );
// setup execution parameters
dim3 dimBlock(BLOCKDIM, 1, 1);
int n_blocks = N/MAX_TERMS_PER_BLOCK + (N%MAX_TERMS_PER_BLOCK == 0 ? 0:1);
dim3 dimGrid(n_blocks, 1, 1);
...
// execute the kernel
qcl1<<< dimGrid, dimBlock >>>(a_d, N, gates, blockGrpSize, k);
// check if kernel execution generated and error
cutilCheckMsg("Kernel execution failed");
...
// copy result from device to host
cudaMemcpy(q->termsarray, a_d, size, cudaMemcpyDeviceToHost);
// stop timer
cutilCheckError( cutStopTimer( timer));
//printf( "GPU Processing time: %f (ms)\n", cutGetTimerValue( timer));
cutilCheckError( cutDeleteTimer( timer));
// cleanup memory on device
cudaFree(a_d);
cudaThreadExit();
}
#endif // #ifndef _CUDA_KERNEL_H_
而“gpu.h”的内容如下:
#ifndef _GPU_H_
#define _GPU_H_
#include "qc/operator.h"
#include "qc/qustates.h"
void gpucaller(opBit* op, quBaseState* q);
#endif // #ifndef _GPU_H_
我的 c++ 文件中不包含 .cu 文件,我只在 c++ 和 .cu 文件中包含 .h 文件(gpu.h - 包含我的内核调用函数的原型)。
我用 nvcc 编译 .cu 文件,并将生成的 .o 文件链接到我的项目的 Makefile 中。 另外,我没有忘记在 Makefile 中添加“-lcudart”标志。
问题是当我编译我的主项目时,我得到了这个错误:
expected primary-expression before ',' token
指的是 extern.cc 中我调用“gpucaller”函数的行。
有谁知道如何解决这个问题?
编辑:我尝试再次编译,这次从 gpucaller 的函数定义中删除了参数(显然没有将任何参数传递给函数,这是错误的,因为我 需要 传递参数)。它编译得很好。
所以问题是 gpucaller 的参数类型无法识别,我不知道为什么(我已经包含了声明参数类型的标头,即“qc/operator .h”和“qc/quStates.h”)。有没有人可以解决这个问题?
我的项目的 Makefile 是这样的:
版本=0.6.3 # 标准 .qcl 文件的目录 QCLDIR = /usr/local/lib/qcl # qcl 二进制文件的路径 QCLBIN = /usr/local/bin ARCH = `g++ -dumpmachine ||回声箱` # 如果要针对不同的目标架构进行编译,请注释掉 # 要构建 libqc.a,您还必须编辑 qc/Makefile! #ARCH = i686-linux #ARCHOPT = -m32 -march=i686 # 调试和优化选项 #DEBUG = -g -pg -DQCL_DEBUG -DQC_DEBUG #DEBUG = -g -DQCL_DEBUG -DQC_DEBUG 调试 = -O2 -g -DQCL_DEBUG -DQC_DEBUG #DEBUG = -O2 # 绘图支持 # # 如果你没有 GNU libplotter 和 X,请注释掉 PLOPT = -DQCL_PLOT PLLIB = -L/usr/X11/lib -lplotter # 阅读线支持 # # 如果您的系统上没有 GNU readline,请注释掉 # 可能需要针对 libtermcap 或 libncurses 的显式链接 RLOPT = -DQCL_USE_READLINE #RLLIB = -lreadline RLLIB = -lreadline -lncurses # 中断支持 # # 如果您的系统不支持 ANSI C 信号处理,请注释掉 IRQOPT = -DQCL_IRQ # 在非 GNU 系统上替换为 lex 和 yacc(未经测试) LEX = 弹性 YACC = 野牛 安装 = 安装 #####你不应该编辑下面的东西##### DATE = `日期 +"%y.%m.%d-%H%M"` QCDIR = 质量控制 QCLIB = $(QCDIR)/libqc.a QCLINC = 库 #CXX = g++ #CPP = $(CC) -E CXXFLAGS = -c $(ARCHOPT) -Wall $(DEBUG) $(PLOPT) $(RLOPT) $(IRQOPT) -I$(QCDIR) -DDEF_INCLUDE_PATH="\"$(QCLDIR)\"" LDFLAGS = $(ARCHOPT) -L$(QCDIR) $(DEBUG) $(PLLIB) -lm -lfl -lqc $(RLLIB) -L"/usr/local/cuda/lib" -lcudart FILESCC = $(通配符 *.cc) FILESH = $(通配符 *.h) 源 = $(FILESCC) $(FILESH) qcl.lex qcl.y Makefile 对象 = types.o syntax.o typcheck.o symbols.o error.o \ lex.o yacc.o print.o quheap.o extern.o eval.o exec.o \ parse.o options.o debug.o cond.o dump.o plot.o format.o cuda_kernel.o 全部:一劳永逸 ifeq (.depend,$(通配符 .depend)) 包括.依赖 万事俱备:构建 别的 万事俱备:dep $(制作) 万一 #### 依赖规则 部门:lex.cc yacc.cc yacc.h $(QCLIB) 对于 *.cc 中的 i;做 \ $(CPP) -I$(QCDIR) -MM $$i; \ 完成 > .depend lex.cc:qcl.lex yacc.h $(LEX) -olex.cc qcl.lex yacc.cc: qcl.y $(YACC) -t -d -o yacc.cc qcl.y yacc.h:yacc.cc mv yacc.*?h yacc.h $(QCLIB): cd $(QCDIR) && $(MAKE) libqc.a #### 构建规则 构建:qcl $(QCLINC)/default.qcl qcl: $(OBJECTS) qcl.o $(QCLIB) $(CXX) $(OBJECTS) qcl.o $(LDFLAGS) -o qcl $(QCLINC)/default.qcl: extern.cc grep "^//!" extern.cc |剪切 -c5- > $(QCLINC)/default.qcl 签到: [ -f ./qcl -a -f $(QCLINC)/default.qcl ] || $(MAKE) 构建 安装:checkinst $(安装) -m 0755 -d $(QCLBIN) $(QCLDIR) $(安装) -m 0755 ./qcl $(QCLBIN) $(安装) -m 0644 ./$(QCLINC)/*.qcl $(QCLDIR) 卸载: -rm -f $(QCLBIN)/qcl -rm -f $(QCLDIR)/*.qcl -rmdir $(QCLDIR) #### 其他功能 编辑: nedit $(SOURCE) & 干净的: rm -f *.o lex.* yacc.* cd $(QCDIR) && $(MAKE) 清洁 清:干净 rm -f qcl $(QCLINC)/default.qcl .depend cd $(QCDIR) && $(MAKE) 清除 dist-src:dep mkdir qcl-$(版本) cp README 更改复制 .depend $(SOURCE) qcl-$(VERSION) mkdir qcl-$(版本)/qc cp qc/Makefile qc/*.h qc/*.cc qcl-$(VERSION)/qc cp -r lib qcl-$(版本) tar czf qcl-$(VERSION).tgz --owner=0 --group=0 qcl-$(VERSION) rm -r qcl-$(版本) dist-bin: 构建 mkdir qcl-$(VERSION)-$(ARCH) cp Makefile README 更改复制 qcl qcl-$(VERSION)-$(ARCH) cp -r lib qcl-$(VERSION)-$(ARCH) tar czf qcl-$(VERSION)-$(ARCH).tgz --owner=0 --group=0 qcl-$(VERSION)-$(ARCH) rm -r qcl-$(VERSION)-$(ARCH) 上传:dist-src scp qcl-$(VERSION)*.tgz oemer@tph.tuwien.ac.at:html/tgz scp:dist-src scp qcl-$(VERSION).tgz oemer@tph.tuwien.ac.at:bak/qcl-$(DATE).tgz我添加到原始 Makefile 的唯一更改是将“cuda_kernel.o”添加到 OBJECTS' 行,并将“-lcudart”标志添加到 LDFLAGS。
更新:感谢 harrism 帮助我。我正在传递一个类型作为参数。
【问题讨论】:
-
我认为您需要添加更多信息。您能否包含一个更完整的调用代码示例,包括实际类型?我认为正如 lurscher 所说,错误是编译器没有看到 type1 的声明(缺少包含文件?)。
-
我已经更新了我的问题,感谢您的帮助。
-
不知道它与此有关,但不要命名您的头文件 cuda.h。那是 CUDA 的实际包含文件之一。也许这会导致问题。
-
我已经重命名了我的标题,但我仍然收到该错误。
标签: c++ g++ cuda linker-errors