如何使用 CUDA C 快速压缩稀疏数组?

2024-01-23

Summary

Array [A - B - - - C]在设备内存中但想要[A B C]- 使用 CUDA C 最快的方法是什么?

Context

我有一个数组A设备 (GPU) 内存上的整数。在每次迭代中,我随机选择一些大于 0 的元素并从中减去 1。我维护一个排序的查找数组L等于 0 的元素:

Array A:
       @ iteration i: [0 1 0 3 3 2 0 1 2 3]
   @ iteration i + 1: [0 0 0 3 2 2 0 1 2 3]

Lookup for 0-elements L:
       @ iteration i: [0 - 2 - - - 6 - - -]  ->  want compacted form: [0 2 6]
   @ iteration i + 1: [0 1 2 - - - 6 - - -]  ->  want compacted form: [0 1 2 6]

(在这里,我随机选择元素1 and 4从中减去 1。在我的 CUDA C 实现中,每个线程映射到A,因此查找数组是稀疏的,以防止数据竞争并保持排序顺序(例如[0 1 2 6]而不是[0 2 6 1]).)

稍后,我将只对那些等于 0 的元素进行一些操作。因此我需要压缩我的稀疏查找数组L,这样我就可以将线程映射到 0 个元素。

因此,使用 CUDA C 在设备内存上压缩稀疏数组的最有效方法是什么?

非常感谢。


假设我有:

int V[] = {1, 2, 0, 0, 5};

而我想要的结果是:

int R[] = {1, 2, 5}

实际上,我们正在删除零元素,或者仅复制非零元素。

#include <thrust/device_ptr.h>
#include <thrust/copy.h>
#include <stdio.h>
#define SIZE 5

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)

  struct is_not_zero
  {
    __host__ __device__
    bool operator()(const int x)
    {
      return (x != 0);
    }
  };



int main(){

  int V[] = {1, 2, 0, 0, 5};
  int R[] = {0, 0, 0, 0, 0};
  int *d_V, *d_R;

  cudaMalloc((void **)&d_V, SIZE*sizeof(int));
  cudaCheckErrors("cudaMalloc1 fail");
  cudaMalloc((void **)&d_R, SIZE*sizeof(int));
  cudaCheckErrors("cudaMalloc2 fail");

  cudaMemcpy(d_V, V, SIZE*sizeof(int), cudaMemcpyHostToDevice);
  cudaCheckErrors("cudaMemcpy1 fail");

  thrust::device_ptr<int> dp_V(d_V);
  thrust::device_ptr<int> dp_R(d_R);
  thrust::copy_if(dp_V, dp_V + SIZE, dp_R, is_not_zero());

  cudaMemcpy(R, d_R, SIZE*sizeof(int), cudaMemcpyDeviceToHost);
  cudaCheckErrors("cudaMemcpy2 fail");

  for (int i = 0; i<3; i++)
    printf("R[%d]: %d\n", i, R[i]);

  return 0;


}

结构定义为我们提供了一个测试零元素的函子。请注意,在推力中,没有内核,我们也没有直接编写设备代码。所有这一切都发生在幕后。我绝对建议您熟悉快速入门指南 https://github.com/thrust/thrust/wiki/Quick-Start-Guide,以免把这个问题变成推力教程。

查看评论后,我认为代码的修改版本将解决 cuda 4.0 问题:

#include <thrust/device_ptr.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <stdio.h>
#define SIZE 5

  struct is_not_zero
  {
    __host__ __device__
    bool operator()(const int x)
    {
      return (x != 0);
    }
  };



int main(){

  int V[] = {1, 2, 0, 0, 5};
  int R[] = {0, 0, 0, 0, 0};

  thrust::host_vector<int> h_V(V, V+SIZE);
  thrust::device_vector<int> d_V = h_V;
  thrust::device_vector<int> d_R(SIZE, 0);

  thrust::copy_if(d_V.begin(), d_V.end(), d_R.begin(), is_not_zero());
  thrust::host_vector<int> h_R = d_R;

  thrust::copy(h_R.begin(), h_R.end(), R);

  for (int i = 0; i<3; i++)
    printf("R[%d]: %d\n", i, R[i]);

  return 0;


}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 CUDA C 快速压缩稀疏数组? 的相关文章

  • CUDA全局内存事务的成本

    根据 CUDA 5 0 编程指南 如果我同时使用 L1 和 L2 缓存 在 Fermi 或 Kepler 上 则所有全局内存操作都使用 128 字节内存事务完成 但是 如果我仅使用 L2 则使用 32 字节内存事务 第 F 4 2 章 让我
  • 优化三角矩阵计算的 CUDA 内核的执行

    我正在开发我的第一个 Cuda 应用程序 并且我的内核 吞吐量低于预期 这似乎是目前最大的瓶颈 内核的任务是计算一个 N N 大小的矩阵 DD 包含数据矩阵上所有元素之间的平方距离 数据矩阵 Y 的大小为 N D 以支持多维数据 并存储为行
  • C 中带括号和不带括号的循环处理方式不同吗?

    我在调试器中单步执行一些 C CUDA 代码 如下所示 for uint i threadIdx x i lt 8379 i 256 sum d PartialHistograms blockIdx x i HISTOGRAM64 BIN
  • 无法从静态初始化代码启动 CUDA 内核

    我有一个在其构造函数中调用内核的类 如下所示 标量场 h include
  • 使用常量内存打印地址而不是cuda中的值

    我试图在代码中使用常量内存 并从内核分配常量内存值 而不是使用 cudacopytosymbol include
  • 如何在 gitlab-ci docker 执行器中使用 cuda

    我们正在使用 gitlab 持续集成来构建和测试我们的项目 最近 其中一个项目添加了 CUDA 的要求以启用 GPU 加速 我不想改变我们的管道 docker 和 gitlab ci 对我们来说运行良好 所以我想以某种方式让 docker
  • Ubuntu 11.10/12.04 上的 CUDA“无兼容设备”错误

    一段时间以来 我一直在尝试在我的笔记本电脑上设置 Ubuntu 环境来进行 CUDA 编程 我目前双启动 Windows 8 和 Ubuntu 12 04 并想在 Ubuntu 上安装 CUDA 5 该笔记本电脑配有 GeForce GT
  • 将 GPUJPEG 项目移植到 Windows

    我目前正在尝试移植 GPUJPEG 在 Sourceforge 上 http sourceforge net projects gpujpeg 库 基于 CUDA 从 Unix 到 Windows 现在我被卡住了 我不知道发生了什么或为什么
  • 某些子网格未使用 CUDA 动态并行执行

    我正在尝试 CUDA 5 0 GTK 110 中的新动态并行功能 我遇到了一个奇怪的行为 即我的程序没有返回某些配置的预期结果 不仅是意外的 而且每次启动都会出现不同的结果 现在我想我找到了问题的根源 似乎当生成太多子网格时 某些子网格 由
  • 在新线程中调用支持 CUDA 的库

    我编写了一些代码并将其放入它自己的库中 该库使用 CUDA 在 GPU 上进行一些处理 我正在使用 Qt 构建 GUI 前端 作为加载 GUI 的一部分 我调用 CUresult res CUdevice dev CUcontext ctx
  • 在 cuda 的 nvcc 编译器中使用 C++20

    我正在尝试使用std countr zero 函数从
  • 同时使用 2 个 GPU 调用 cudaMalloc 时性能较差

    我有一个应用程序 可以在用户系统上的 GPU 之间分配处理负载 基本上 每个 GPU 都有一个 CPU 线程来启动一个GPU处理间隔当由主应用程序线程定期触发时 考虑以下图像 使用 NVIDIA 的 CUDA 分析器工具生成 作为示例GPU
  • 传递给 CUDA 的结构中的指针

    我已经搞砸了一段时间了 但似乎无法正确处理 我正在尝试将包含数组的对象复制到 CUDA 设备内存中 然后再复制回来 但当我遇到它时我会跨过那座桥 struct MyData float data int dataLen void copyT
  • 如何优化这个 CUDA 内核

    我已经分析了我的模型 似乎该内核约占我总运行时间的 2 3 我一直在寻找优化它的建议 代码如下 global void calcFlux double concs double fluxes double dt int idx blockI
  • 如何并行从数组中删除零值

    如何使用 CUDA 并行有效地从数组中删除零值 有关零值数量的信息是预先可用的 这应该可以简化这项任务 重要的是数字必须保持源数组中的顺序 当被复制到结果数组时 Example 该数组将例如包含以下值 0 0 19 7 0 3 5 0 0
  • CUDA线程执行顺序

    我有一个 CUDA 程序的以下代码 include
  • Nvcc 的版本与 CUDA 不同

    我安装了 cuda 7 但是当我点击 nvcc version 时 它打印出 6 5 我想在 GTX 960 卡上安装 Theano 库 但它需要 nvcc 7 0 我尝试重新安装cuda 但它没有更新nvcc 当我运行 apt get i
  • Yocto for Nvidia Jetson 由于 GCC 7 而失败 - 无法计算目标文件的后缀

    我正在尝试将 Yocto 与 meta tegra 一起使用 https github com madisongh meta tegra https github com madisongh meta tegra 为 Nvidia Jets
  • cuda中有模板化的数学函数吗? [复制]

    这个问题在这里已经有答案了 我一直在寻找 cuda 中的模板化数学函数 但似乎找不到 在普通的 C 中 如果我调用std sqrt它是模板化的 并且将根据参数是浮点数还是双精度数执行不同的版本 我想要这样的 CUDA 设备代码 我的内核将真
  • 从 CUDA 设备写入输出文件

    我是 CUDA 编程的新手 正在将 C 代码重写为并行 CUDA 新代码 有没有一种方法可以直接从设备写入输出数据文件 而无需将数组从设备复制到主机 我假设如果cuPrintf存在 一定有地方可以写一个cuFprintf 抱歉 如果答案已经

随机推荐