如何在多个.cpp和.cu文件之间分割类定义

How to split class definition between multiple .cpp and .cu files?

本文关键字:之间 文件 分割 定义 cu cpp      更新时间:2023-10-16

我有一个类嵌套类混合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

  • 我读过推力只能与.cu文件一起使用。因为我的父类cls声明像B这样的推力类型变量(因此#includethrust/device_vector.h),这是否强制所有#include cls.h的文件被制作成.cu文件?

  • 在这种情况下我在哪里使用extern "C" ?我想cls.cpp会要求.cu文件中的所有函数都包装在extern "C"中,但是.cu.cu调用如何,比如moreThrust()调用bar::thrustStuff()

  • 我也知道类的成员不与extern "C"工作,所以我必须为每个成员函数写一个extern "C"包装器函数吗?

我完全困惑于如何使这一切工作- #include s和extern "C" s的鸡尾酒我需要每个文件?

以您的小示例为例,这对我来说编译和运行良好

/*
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("kernelWrappern");
}
/*
Inside File bar.cu
*/
#include "cls.h"
void cls::bar::thrustStuff()
{
    printf("Thrust Stuffn");
}
/*
Inside File cls.cpp
*/
#include "cls.h"
void cls::pureCPP()
{
    printf("pureCPPn");
}
/*
Inside File cls.cu
*/
#include "cls.h"
void cls::moreThrust()
{
    printf("moreThrustn");
}

/*
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问题