【问题标题】:How to split class definition between multiple .cpp and .cu files?如何在多个 .cpp 和 .cu 文件之间拆分类定义?
【发布时间】:2013-05-10 03:49:34
【问题描述】:

我有一个包含混合 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 声明了像B 这样的推力类型变量(因此#includes thrust/device_vector.h),这是否会强制将所有#include cls.h 的文件制作成.cu 文件?

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

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

我完全不知道如何让这一切正常工作 - 每个文件我需要 #includes 和 extern "C"s 的什么鸡尾酒?

【问题讨论】:

  • 你根本不需要 extern "C"。那是从旧时代开始的,当时所有的 CUDA 代码都被视为 C 而不是 C++,因此您必须非常具体地了解名称修饰。 CUDA 文件现在是 C++
  • @alrikai - 但我的编译器也非常清楚地表明,我不能随意混合.cu.cpp 文件之间的调用。事实上,提供.cpp 访问.cu 内核的内核包装器似乎只适用于extern "C"
  • 您使用的是最新版本吗?
  • 或者我已经迫不及待地将我所有的 .cpp 重命名为 .cu 文件 - 但我仍然无法让它工作。我得到恒定的function [x] referenced but not defined 错误
  • 你不应该重命名任何东西。试试我的答案中的代码,让我知道它是否适合你

标签: c++ class cuda gpgpu thrust


【解决方案1】:

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

/*
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__。见this other SO question

【讨论】:

  • 好的,谢谢。我来自 C,所以我犯了一个新手错误,没有放置模板或内联它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 2015-06-01
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2020-12-29
相关资源
最近更新 更多