【问题标题】:Include cuda kernel in my project在我的项目中包含 cuda 内核
【发布时间】: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


【解决方案1】:
gpucaller(opBit, q);  

您将类型名称 (opBit) 作为函数参数传递,这不是有效的 C 或 C++。看起来您需要这样做:

gpucaller(op, q);  

【讨论】:

  • 谢谢,我因此浪费了2天,我需要更加小心。
【解决方案2】:

cuda.h 中真的看起来像这样吗?

void gpucaller(type1 param1, type2 param2);

是否在任何地方声明了 type1type2,以便您的常规 C++ 编译器知道这些类型是什么?如果没有,那么你会得到一个错误,就像你说的那样。

【讨论】:

  • 不,它们有不同的类型并且编译得很好(我已经在它们的定义中包含了标题),我只是想简单介绍一下我正在处理的内容。
【解决方案3】:

您的问题代码目前非常庞大且复杂。尝试将其简化为更简单的失败案例,并在遇到问题后更新您的问题。这将使尝试复制变得更容易。去掉 cuda 计时器代码,switch case,在无关紧要的地方用... 替换实现细节,等等。

我用 msvc 和 nvcc 编译然后用 icl 链接;因此,如果您可以制作一个简单的示例,我可以查看它是否使用完全不同的编译器设置进行编译。这应该可以缩小问题的范围。


尽管将您自己的标题 cuda.h 重命名为 somethingspecific.h 没有帮助,但我认为将其保留为 cuda.h 并不是一个好主意。这很令人困惑,也是潜在的问题根源。

【讨论】:

猜你喜欢
  • 2011-06-14
  • 2012-06-03
  • 1970-01-01
  • 2018-06-02
  • 2021-02-07
  • 2013-11-06
  • 2014-08-25
  • 1970-01-01
  • 2017-08-20
相关资源
最近更新 更多