【问题标题】:How to include several source files in Nsight Eclipse?如何在 Nsight Eclipse 中包含多个源文件?
【发布时间】:2013-10-06 18:16:39
【问题描述】:

我有一个包含许多源文件的项目(例如:main.cu、a.cu、b.cu、c.cu、d.cu)。每个都有函数和内核调用(globaldevice)。

在一个头文件 (cpu.h) 中,所有在主机端使用的结构和定义。 另一个头文件(gpu.h)所有的结构和定义要在设备端使用。

  1. 如果我从 ma​​in.cu 调用内核函数,在 a.cu 中声明。如何在 a.cu 中声明的那些内核函数#includema​​in.cu 中使用,而不执行 not strong> 推荐#include "a.cu"

  2. 我是否在 a.cu 中创建带有内核函数前向声明的标头 a.h?例子: extern void functionA(type);

那么 CUDA 内核函数呢?我应该为从另一个源文件中使用的每个源文件创建一个头文件吗?

  • 在哪里可以找到一些包含多个源文件的简单 CUDA 示例?

我提到 Nsight Eclipse 是因为我在使用它和多个来源时遇到了很多问题。 我在 Ubuntu Linux 和 Mac OS 环境中使用 CUDA 5.5 Toolkits。 我的主要开发环境是在 Ubuntu Linux 机器上使用 4 个 Tesla C1060 卡。

【问题讨论】:

    标签: linux eclipse cuda include nsight


    【解决方案1】:
    1. 分离内核。在一个项目中,创建两个文件(我重构了默认的Runtime Project模板并创建了device.cu和host.cu)

      device.cu:

      __device__ unsigned int bitreverse(unsigned int number) {
          number = ((0xf0f0f0f0 & number) >> 4) | ((0x0f0f0f0f & number) << 4);
          number = ((0xcccccccc & number) >> 2) | ((0x33333333 & number) << 2);
          number = ((0xaaaaaaaa & number) >> 1) | ((0x55555555 & number) << 1);
          return number;
      }
      
      __global__ void bitreverse(void *data) {
          unsigned int *idata = (unsigned int*) data;
          idata[threadIdx.x] = bitreverse(idata[threadIdx.x]);
      }
      

      host.cu:

      extern __global__ void bitreverse(void *data);
      
      ...
      
      bitreverse<<<1, WORK_SIZE, WORK_SIZE * sizeof(int)>>>(d);
      
    2. 单独编译

      1. 右键单击项目,转到属性。
      2. 构建/设置。
      3. 为 SM 2.0 或更高版本设置构建。
      4. 选择“单独编译”单选。

      device.cu:

      __device__ unsigned int bitreverse(unsigned int number) {
          number = ((0xf0f0f0f0 & number) >> 4) | ((0x0f0f0f0f & number) << 4);
          number = ((0xcccccccc & number) >> 2) | ((0x33333333 & number) << 2);
          number = ((0xaaaaaaaa & number) >> 1) | ((0x55555555 & number) << 1);
          return number;
      }
      

      host.cu:

      extern __device__ unsigned int bitreverse(unsigned int number);
      
      __global__ void bitreverse(void *data) {
          unsigned int *idata = (unsigned int*) data;
          idata[threadIdx.x] = bitreverse(idata[threadIdx.x]);
      }
      
      ...
      
      bitreverse<<<1, WORK_SIZE, WORK_SIZE * sizeof(int)>>>(d);
      
    3. 隔离 CUDA 代码 一种常见的模式是将 CUDA 代码隔离在 .cu 文件中,这些文件具有封装内核调用的宿主函数。通过这种方式,您可以将此类 .cu 文件生成的目标文件链接到以 .cpp 或 .c 文件编写的主机代码。请记住,导出的主机代码函数应使用 extern "C" 进行限定,以便可从 .c 文件中使用。

    extern 声明可以放在 .h 文件中。请注意,具有 CUDA C 语法的 .h 文件(__global__ 是 CUDA C 特定的)不能包含在 .cpp 或 .c 中。

    向项目添加文件

    通常我只是将文件复制到项目文件夹,右键单击项目并执行“刷新”。 Nsight 会将它们编入索引并包含在构建中。

    从构建中排除文件

    如果您绝对需要,您可以将设备代码复制到标头并包含标头(惯例是此类头文件具有 .cuh 扩展名,尽管 .h 的工作方式相同)。您可以包含 .cu - 问题是 Nsight 将此类文件视为源文件并尝试编译它们。您可以通过选中构建属性中构建子树中任何属性页面顶部的“从构建中排除资源”复选框来从构建中排除 .cu 文件。

    CUDA 多文件示例

    几乎所有重要的样本都被分解成多个文件。只需从例如“粒子”示例创建一个 Nsight 项目。

    【讨论】:

    • 有些部分看不懂。为什么你在 device.cu 中有两个 bitreverse 内核函数?我认为一个是您的全局内核功能,另一个是设备。他们可以有相同的名字吗?
    • 哦,对 :) 有两个同名的函数有点不整洁——我只是让它们表明内核(__global__)和设备(__device__)函数都可以在一个不同的文件。请注意,bitreverse 函数名称被不同的参数列表重载。您不能仅通过 CUDA 声明说明符覆盖(例如,您不能拥有具有相同名称和参数列表的 __global____device__ 函数)。
    • SM 1.3 不支持单独编译(引用来自不同源文件的__device__ 函数)。您仍然可以使用方法 [1](将内核放入单独的源文件)或 [3] - 提供与设备代码位于同一 .cu 中的主机包装器。
    • 如何处理像template __global__ void MCMLKernel(SimState d_state, GPUThreadStates tstates)这样的内核函数?我如何extern 从单独的来源调用它?
    • 模板内核应该在头文件中,与其他 C++ 模板相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 2021-01-06
    • 2010-11-30
    • 2018-04-16
    • 2014-10-06
    • 1970-01-01
    • 2014-11-18
    相关资源
    最近更新 更多