c++ - 如何在 CUDA 设备上更改稀疏矩阵的子矩阵

标签 c++ arrays cuda sparse-matrix

我有一个稀疏矩阵结构,我将其与 CUBLAS 结合使用来实现线性求解器类。我预计我要求解的稀疏矩阵的维数会相当大(大约为 10^7 x 10^7)。 我还将预计求解器将需要多次使用,并且该矩阵的一部分也将需要更新多次(在计算解决方案之间)。

将整个矩阵结构从系统内存复制到设备内存可能会成为性能瓶颈,因为在给定时间只需要更改矩阵条目的一小部分。

我希望能够做的是有一种方法只更新特定的子集/子矩阵,而不是每次我需要更改矩阵时将整个矩阵结构从系统内存重新复制到设备内存.

矩阵数据结构将驻留在数组中的 CUDA 设备上: d_col、d_row 和 d_val

在系统方面,我会有相应的数组 I、J 和 val。

因此,理想情况下,我只想更改与系统数组 val 中的值对应的 d_val 子集。

请注意,我预计矩阵中不会添加或删除任何条目,只有现有条目的值会发生变化。

我天真地认为要实现这个,我会在主机端有一个整数数组或 vector ,例如updateInds ,这将跟踪 val 中已更改的条目的索引,但我不确定如何有效地告诉 CUDA 设备更新 d_val 的相应值。

本质上:如何将 CUDA 设备端数组 (d_val) 中位于索引 updateInds[1]、updateInds[2]、...、updateInds[n] 的条目更改为一组新值 val[updatInds [1]], val[updateInds[2]], ..., val[updateInds[3]],没有将整个 val 数组从系统内存重新复制到 CUDA 设备内存数组 d_val 中?

最佳答案

只要您只想更改与 CSR(或 CSC,或 COO)稀疏矩阵表示相关联的值数组的数值,过程并不复杂。

假设我有这样的代码(摘自 CUDA 共轭梯度 sample ):

checkCudaErrors(cudaMalloc((void **)&d_val, nz*sizeof(float)));
...
cudaMemcpy(d_val, val, nz*sizeof(float), cudaMemcpyHostToDevice);

现在,在代码中的这一点之后,假设我需要更改 d_val 数组中的一些值,对应于我在 val 中所做的更改:

for (int i = 10; i < 25; i++)
  val[i] = 4.0f;

移动这些特定更改的过程在概念上与使用 memcpy 更新数组相同,但我们将使用 cudaMemcpy 来更新 d_val 设备上的数组:

cudaMemcpy(d_val+10, val+10, 15*sizeof(float), cudaMempcyHostToDevice);

由于这些值都是连续的,我可以使用单个 cudaMemcpy 调用来实现传输。

如果我有多个与上述类似的不相交区域,则需要多次调用 cudaMemcpy,每个区域调用一次。如果碰巧这些区域间隔相等且长度相等:

for (int i = 10; i < 5; i++)
  val[i] = 1.0f;
for (int i = 20; i < 5; i++)
  val[i] = 2.0f;
for (int i = 30; i < 5; i++)
  val[i] = 4.0f;

然后也可以使用对 cudaMemcpy2D 的单个调用来执行此传输。方法概述here .

注意事项:

  1. cudaMemcpy2D相同数量的元素 上的 cudaMemcpy 操作相比,比您预期的要慢。
  2. CUDA API 调用有一些固有的开销。如果矩阵的大部分要以分散的方式更新,实际上只传输整个 d_val 数组可能仍然更快,因为这可以使用单个cudaMemcpy操作。
  3. 如果非零值改变了它们在稀疏矩阵中的位置,则不能使用这里描述的方法。在这种情况下,我无法就如何通过外科手术更新设备上的 CSR 稀疏矩阵提供一般性答案。无论如何,某些相对简单的更改可能需要更新大部分数组数据(3 个 vector )。

关于c++ - 如何在 CUDA 设备上更改稀疏矩阵的子矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30988492/

相关文章:

c++ - 是否有用于阻塞 boost::asio TCP 连接的 boost::iostreams(双向)设备?

c++ - 初始化类的静态(非常量)变量。

c++ - cudaMemcpyToSymbol : zero value in __constant__ variable

c++ - C++ 中的 3d 卷积

arrays - BigQuery 类型 : How to define a array of any type?

c - 什么情况下无法展开循环?

c++ - 在 32 位和 64 位程序中使用 std::chrono::duration::rep 和 printf

c++ - 来自成员函数返回的临时值的基于范围的循环

java - 有没有办法 println 来枚举和列出字符串中的单词?

arrays - Scala 中的 Array 和 WrappedArray 有什么区别