【问题标题】:How to work with Eigen in CUDA kernels如何在 CUDA 内核中使用 Eigen
【发布时间】:2014-05-22 09:00:11
【问题描述】:

Eigen 是一个 c++ 线性代数库http://eigen.tuxfamily.org

使用基本数据类型(如基本浮点数组)很容易,只需将其复制到设备内存并将指针传递给 cuda 内核。但是 Eigen 矩阵是复杂类型,如何将其复制到设备内存并让 cuda 内核读取/写入呢?

【问题讨论】:

  • 这是一个严重依赖Eigen的遗留项目,所以最好不要替换它
  • 更简单的方法可能是在使用设备之前切换到 CUBLAS,如果 eigen 不是为在 GPU 上工作而设计的,你就不能使用它(或者你会得到可怕的错误 /表演)。还要看看统一内存,可能会为您节省一些复制的麻烦(或者如果您想要完全控制自己做)
  • 有没有办法从 eigen 获取原始数据指针,比如 float *?
  • “特征矩阵是复杂类型”是什么意思?请注意,在这种情况下,复杂类型可以是 std::complex<double>。您可以在本征中拥有真正的矩阵...您的问题很混乱:“使用基本数据类型(如基本浮点数组)很容易,只需将其复制到设备内存并将指针传递给 cuda 内核。 i>",您的意思是 Eigen 易于使用普通类型或 CUDA?

标签: c++ cuda eigen


【解决方案1】:

自 2016 年 11 月(Eigen 3.3 发布)以来,存在一个新选项:在 CUDA 内核中直接使用 Eigen - 请参阅 this question

来自链接问题的示例:

__global__ void cu_dot(Eigen::Vector3f *v1, Eigen::Vector3f *v2, double *out, size_t N)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if(idx < N)
    {
        out[idx] = v1[idx].dot(v2[idx]);
    }
    return;
}

Eigen::Vector3f 的数组复制到设备:

Eigen::Vector3f *host_vectors = new Eigen::Vector3f[N];
Eigen::Vector3f *dev_vectors;
cudaMalloc((void **)&dev_vectors, sizeof(Eigen::Vector3f)*N)
cudaMemcpy(dev_vectors, host_vectors, sizeof(Eigen::Vector3f)*N, cudaMemcpyHostToDevice)

【讨论】:

    【解决方案2】:

    如果您只想通过原始 C 指针访问 Eigen::Matrix 的数据,那么您可以使用 .data() 函数。默认情况下,系数按列主要顺序存储在内存中,如果您要求,则按行主要顺序存储:

    MatrixXd A(10,10);
    double *A_data = A.data();
    

    【讨论】:

    • @MickeyShine:请注意,这类似于您将 CUDA 与包含 POD 结构的 STL 向量一起使用时可以执行的操作。正如 ggael 所说,请注意默认存储顺序。
    【解决方案3】:

    除了重写和修改代码之外,还有一个 Eigen 兼容库,作为在 GPU 上执行矩阵计算的研究项目的副产品编写,您可以使用多个后端: https://github.com/rudaoshi/gpumatrix

    我不能保证它,但如果它有效,它可能正是您正在寻找的。​​p>

    如果您想要更通用的解决方案,this thread 似乎包含非常有用的信息

    【讨论】:

    • 似乎是最简单的方法,这个或普通的 C 数组。由我 +1
    【解决方案4】:

    有两种方法。

    让 eigen 在 GPU 上工作,这可能很难并且性能不佳。至少如果在 GPU 上工作意味着只让它编译和产生结果。 Eigen 实际上针对现代 CPU 进行了手动优化。在内部,Eigen 使用自己的分配器和内存布局,这很可能无法在 CUDA 上正常工作。

    第二种方法更容易做,不应该破坏遗留的 Eigen 代码,并且可能是唯一适合你的情况。使用Eigen::Map 将您的基础矩阵切换为普通矩阵(即double**)。这样,您将拥有到普通数据类型的 Eigen 接口,因此代码不应中断,并且您可以像通常所做的那样将矩阵作为普通 c 数组发送到 GPU。缺点是您可能无法充分利用 Eigen,但是如果您将大部分工作转移到 GPU 上,那也没关系。

    它实际上有点扭转了局面。您可以让 Eigen 在普通数组上工作,而不是让 Eigen 数组在 CUDA 上工作。

    【讨论】:

    • 第二个可能是一种方法。谢谢大家
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 2016-10-10
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    相关资源
    最近更新 更多