【发布时间】:2019-06-19 20:19:21
【问题描述】:
我有一个非常简单的字符串类,分别在 StringT.cu 和 StringT.cpp 中声明和定义。
StringT.cu
#ifndef STRING_T_CU
#define STRING_T_CU
#include "cuda_runtime.h"
class StringT
{
public:
static const int MAX_LEN = 15;
__host__ __device__ StringT(char const * s);
__host__ __device__ ~StringT();
__host__ __device__ char* Get();
private:
char* str;
};
#endif
StringT.cpp
#include "StringT.cu"
#include <stdlib.h>
#include <malloc.h>
StringT::StringT(char const * s)
{
str = (char*)malloc(MAX_LEN + 1);
int k;
for (k = 0; *s != NULL; ++s, ++k) {
if (k > MAX_LEN) {
break;
}
str[k] = *s;
}
str[k] = '\0';
}
StringT::~StringT()
{
free(str);
}
char* StringT::Get()
{
return str;
}
我想简单地调用 kernel.cu 中的类。
kernel.cu
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include "StringT.cu"
#include "CudaUtil.h"
__global__ void kernel()
{
StringT s("aa");
printf("%s", s.Get());
}
int main()
{
kernel <<< 1, 1 >>> ();
checkCudaErrors(cudaDeviceSynchronize());
checkCudaErrors(cudaGetLastError());
return 0;
}
但是这段代码编译失败,出现如下错误:
1>CUDALINK:nvlink 错误:“Debug/kernel.cu.obj”中对“_ZN7StringTC1EPKc”的未定义引用
1>CUDALINK:nvlink 错误:“Debug/kernel.cu.obj”中对“_ZN7StringT3GetEv”的未定义引用
1>CUDALINK:nvlink 错误:在“Debug/kernel.cu.obj”中未定义对“_ZN7StringTD1Ev”的引用
如您所见,所有方法都已定义。我还尝试按照this 帖子的指示更改运行时库。我应该补充一点,当我计划使用动态并行时,我启用了可重定位设备代码。同时,我确实遇到了this 文档,并在“在 CUDA 中使用单独编译”部分找到了一些说明。但是,我在这个项目中使用了 Visual Studio,并且不确定如何更改编译器设置。我尝试将各种东西添加到
C/C++ -> 命令行 -> 附加选项
CUDA C/C++ -> 命令行 -> 附加选项
链接器 -> 命令行 -> 附加选项
CUDA 链接器 -> 命令行 -> 附加选项
但仍然没有得到它的工作。有人知道吗?
已编辑 我重命名了包含字符串类的声明和定义的文件:
StringT.cuh
#ifndef STRING_T_CUH
#define STRING_T_CUH
#include "cuda_runtime.h"
class StringT
{
public:
static const int MAX_LEN = 15;
__host__ __device__ StringT(char const * s);
__host__ __device__ ~StringT();
__host__ __device__ char* Get();
private:
char* str;
};
#endif
StringT.cu
#include "StringT.cuh"
#include <stdlib.h>
#include <malloc.h>
__host__ __device__ StringT::StringT(char const * s)
{
str = (char*)malloc(MAX_LEN + 1);
int k;
for (k = 0; *s != NULL; ++s, ++k) {
if (k > MAX_LEN) {
break;
}
str[k] = *s;
}
str[k] = '\0';
}
__host__ __device__ StringT::~StringT()
{
free(str);
}
__host__ __device__ char* StringT::Get()
{
return str;
}
我使用 CUDA 8.0 安装中的 vs 集成选项附带的模板创建了项目,将可重定位代码更改为 true 并将 arch 更改为 sm_61、compute_61(我有 GTX 1080 Ti)。
在我将输出详细程度更改为详细信息后,错误消息是:
1>CUDALINK:nvlink 错误:“Debug/kernel.cu.obj”中对“_ZN7StringTC1EPKc”的未定义引用
1>CUDALINK:nvlink 错误:“Debug/kernel.cu.obj”中对“_ZN7StringT3GetEv”的未定义引用
1>CUDALINK:nvlink 错误:在“Debug/kernel.cu.obj”中未定义对“_ZN7StringTD1Ev”的引用
另一方面,我确实设法通过扩展一个示例项目“simpleSeparateCompilation”来编译和运行代码。但是,我看不到任何额外的命令行选项。现在这对我有用,但当然我还没有解决原来的问题。
【问题讨论】:
-
您不能在 .cpp 文件中包含类成员函数的定义。如果这样做,将永远不会为 GPU 编译任何代码
-
感谢您的回复。如果我将 .cpp 文件重命名为“StringTDef.cu”,我会收到如下错误:命令“nvcc ....”与代码 255 一起存在。但是相同的代码在没有 host 的情况下也可以编译b>device 限定符,但 ofc 没有生成设备代码。我想将声明和定义分开,因为我需要将标头包含在不同的文件中并避免多重定义错误。我该怎么做?
-
您引用的错误只是表明编译失败。您能否将更新的代码和实际错误编辑到您的问题中。一般来说,您必须在 .cu 文件中添加注释
__device__ __host__,否则它将不起作用。您可以将声明和定义分开,这没问题。无论您遇到什么其他错误,都与我建议的更改无关 -
谢谢。我已经更新了这个问题。至于 kernel.cu 文件,我更新了代码以包含“StringT.cuh”。
-
如果您打算在不同的 .cu 文件中定义的内核中使用类中的设备函数,则需要使用单独的编译和设备链接
标签: visual-studio visual-studio-2013 cuda