0

我有一个包含混合 C++、CUDA 和 Thrust 的嵌套类的类。我想将成员定义拆分到多个文件中。

// In cls.h:
#include <thrust/device_vector.h>
class cls {
    class foo {   // define in foo.cu    (include "cls.h")
        kernelWrapper();
    }
    class bar {   // define in bar.cu    (include "cls.h")
        thrust::device_vector A;
        thrustStuff();
    }
    thrust::device_vector B;
    pureCPP();      // define in cls.cpp (include "cls.h")
    moreThrust();   // define in cls.cu  (include "cls.h")
}

在每个定义文件中我都简单地#include "cls.h". 但是,无论我尝试什么,我目前都会遇到各种各样的编译器错误,例如pureCPP was referenced but not defined.

  • 我读过 Thrust 只能用于.cu文件。因为我的父类cls声明了 Thrust 类型的变量,例如B(以及因此#includes thrust/device_vector.h),这是否会强制将所有文件#include cls.h制作成.cu文件?

  • 在这种情况下我应该在哪里使用extern "C"?我想cls.cpp需要将文件中的所有函数都.cu包装在 中,但是要调用extern "C"什么,例如调用.cu.cumoreThrust()bar::thrustStuff()

  • 我还知道类的成员不能使用extern "C",所以我必须extern "C"为每个成员函数编写一个包装函数吗?

对于如何使这一切正常工作,我完全感到困惑-每个文件需要什么#includes 和extern "C"s 的鸡尾酒?

4

1 回答 1

0

以你的小例子为例,这对我来说编译并运行良好

/*
Inside File cls.h
*/
#pragma once
#include <thrust/device_vector.h>
#include <stdio.h>

class cls {

public:
    class foo {   // define in foo.cu    (include "cls.h")
    public:
        void kernelWrapper();
    };

    class bar {   // define in bar.cu    (include "cls.h")
        thrust::device_vector<int> A;
    public:
        void thrustStuff();
    };

public:
    void pureCPP();      // define in cls.cpp (include "cls.h")
    void moreThrust();   // define in cls.cu  (include "cls.h")

private:
    thrust::device_vector<int> B;
};

/*
Inside File foo.cu
*/
#include "cls.h"
void cls::foo::kernelWrapper()
{
    printf("kernelWrapper\n");
}

/*
Inside File bar.cu
*/
#include "cls.h"
void cls::bar::thrustStuff()
{
    printf("Thrust Stuff\n");
}

/*
Inside File cls.cpp
*/
#include "cls.h"
void cls::pureCPP()
{
    printf("pureCPP\n");
}

/*
Inside File cls.cu
*/
#include "cls.h"
void cls::moreThrust()
{
    printf("moreThrust\n");
}


/*
Inside File main.cpp
*/
#include "cls.h"
int main()
{
    cls a_class;
    a_class.pureCPP();
    a_class.moreThrust();

    cls::bar a_class_bar;
    a_class_bar.thrustStuff();

    cls::foo a_class_foo;
    a_class_foo.kernelWrapper();
}

运行此打印

pureCPP

moreThrust

Thrust Stuff

KernelWrapper

如果有的话,我敢打赌你正在使用一个 IDE,它并没有编译你的所有文件,所以虽然你的头文件中有你的类成员声明,​​但它永远不会找到相应的定义。您的确切编译命令会有所不同,但对我来说(在 Linux 上)我使用

nvcc -G -g -O0 -gencode arch=compute_20,code=sm_21 -odir "src" -M -o "src/bar.d" "../src/bar.cu"
nvcc --device-c -G -O0 -g -gencode arch=compute_20,code=sm_21  -x cu -o  "src/bar.o" "../src/bar.cu"

nvcc -G -g -O0 -gencode arch=compute_20,code=sm_21 -odir "src" -M -o "src/cls.d" "../src/cls.cu"
nvcc --device-c -G -O0 -g -gencode arch=compute_20,code=sm_21  -x cu -o  "src/cls.o" "../src/cls.cu"

nvcc -G -g -O0 -gencode arch=compute_20,code=sm_21 -odir "src" -M -o "src/foo.d" "../src/foo.cu"
nvcc --device-c -G -O0 -g -gencode arch=compute_20,code=sm_21  -x cu -o  "src/foo.o" "../src/foo.cu"

nvcc -G -g -O0 -gencode arch=compute_20,code=sm_21 -odir "src" -M -o "src/main.d" "../src/main.cpp"
nvcc -G -g -O0 --compile  -x c++ -o  "src/main.o" "../src/main.cpp"

nvcc -G -g -O0 -gencode arch=compute_20,code=sm_21 -odir "src" -M -o "src/clscpp.d" "../src/cls.cpp"
nvcc -G -g -O0 --compile  -x c++ -o  "src/clscpp.o" "../src/cls.cpp"

nvcc --relocatable-device-code=true -gencode arch=compute_20,code=sm_21 -link -o  "split_compilation"  ./src/bar.o ./src/cls.o ./src/foo.o ./src/clscpp.o ./src/main.o   

这个想法只是编译所有源文件并将它们链接在一起。例如,如果我没有编译和链接 cls.cpp 文件,我会在任何对pureCPP.

另外,请注意,如果您使用的是实际设备代码,则必须为您的成员函数指定__device__和/或__host__。请参阅其他 SO 问题

于 2013-05-09T19:49:34.507 回答