【问题标题】:Using external library classes in CUDA project在 CUDA 项目中使用外部库类
【发布时间】:2012-12-05 16:45:32
【问题描述】:

我正在尝试使用 CUDA 增强一个小型 C++ 项目。 我的项目正在使用自定义库的类和函数,例如 Matrix3d, Vector3d, Plane2d 等。它们主要是几何对象。

当我尝试在设备中使用我的代码(__host__ __device__ 函数或内核)时,所有库函数/对象都被视为主机代码,我收到多个警告和错误,例如 error: identifier "Plane3d::~Plane3d" is undefined in device code

有没有办法在设备上也使用我的库?它是如何完成的? 我没有 CUDA 和 C++ 方面的经验(我只使用 CUDA 和没有类的简单 C 代码)所以我不太了解这个策略。

是否有避免更改库源代码的方法?可以更改库的代码,但如果我能避免它会更好。

非常感谢。

【问题讨论】:

  • 如果库是为CPU使用而编译的,那么如果不对库的源代码进行一些更改并重新构建库,就无法使用它。库以编译对象形式表示代码。编译后的对象由 CPU 机器码组成。 GPU 无法使用或理解 CPU 机器代码。如果您使用适当的 __ device__ __ host__ 装饰和可能的其他更改重新编码库,并通过 nvcc 传递它,这将是能够在设备上使用它的起点。如果库是通用的,那么其他人可能已经这样做了。
  • 没有库是内部的,我可以更改并编译它。只是我将不得不在几乎所有地方添加__device__ __host__ 关键字。

标签: c++ cuda libraries


【解决方案1】:

在 CUDA 中使用 C++ 类没有什么特别的问题。对象模型与标准 C++ 仅略有不同。

任何结构或类数据成员都会在类或结构实例化的任何内存空间(如主机或设备)中自动定义。不自动的是类和结构内的函数成员和运算符的代码生成。程序员必须显式定义和编译那些对象将被实例化的内存空间。后一个要求意味着您必须同时拥有在对象中调用的每个函数的__device____host__ 定义。这包括构造函数和析构函数,后者是您在问题中显示的错误。

【讨论】:

  • 所以这意味着我无法避免为每个库类添加额外的定义?
  • @George Aprilis:基本上是的。如果结构/类具有成员函数,则必须明确定义这些成员函数的 GPU 实现,以便为 GPU 编译代码。
  • 我将尝试按照here 描述的方式更改库。感谢您的帮助。
【解决方案2】:

您不需要更改源代码 - 您需要编写一个适配器。

CUDA 内核适用于低级结构,例如double*、double*、double** 或 float*、float*、float** 以及内置的 CUDA 类型。

无论如何,CUDA 都不能直接在 CUDA 外部分配的内存上工作(仅在显卡上分配内存,而不是常规 RAM),因此您必须将数据复制到显卡内存中。

如果您提供可以访问您的类型使用的缓冲区的方法,您可以将它们复制到图形卡中(使用 CUDA 内存复制功能),如果您的类型有连续内存,或者如果没有连续内存,则以块的形式复制,然后您可以使用简单的索引将它们与内核一起处理为 double***。

【讨论】:

  • CUDA 内核也适用于 C++ 和对象。如果您想要一个可在设备上使用的对象表示,您将需要提供某种类型的对象定义(即不仅仅是 double/float/built-in 类型)。您可以区分主机和设备,但这并不排除需要对对象somewhere 进行适当修饰的设备表示。您可以编写一个适配器而不是重构库,但您将这样做重复。如果您不想在设备上使用对象,则可以使用低级数据类型。
  • 问题是因为它们是基本的几何元素,所以我的许多类都将它们用作组件,并且我还使用了各种函数(例如,Matrix3x3::rotate() 等函数)。它们不仅仅是数据。或者我没有很好地理解你的意思。
  • @GeorgeAprilis 你是对的。如果您想访问对象方法,那么简单地复制数据是行不通的。您需要一个已编译的对象表示以在设备上使用。
  • @RobertCrovella 我会删除我的答案,但失去你的 cmets 会很可惜。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-16
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 2017-04-28
相关资源
最近更新 更多