【问题标题】:Conversion from Matlab CSC to CSR format从 Matlab CSC 转换为 CSR 格式
【发布时间】:2012-07-07 09:43:28
【问题描述】:

我正在使用 mex 桥对 Matlab 中的稀疏矩阵执行一些操作。 为此,我需要将输入矩阵转换为 CSR(压缩行存储)格式,因为 Matlab 将稀疏矩阵存储在 CSC(压缩列存储)中。

我能够得到 value 数组和 column_indices 数组。但是,我正在努力获取 CSR 格式的 row_pointer 数组。是否有任何 C 库可以帮助从 CSC 转换为 CSR?

此外,在编写 CUDA 内核时,将 CSR 格式用于稀疏操作是否有效,或者我应该只使用以下数组:- 行索引、列索引和值?

哪个可以让我更好地控制数据,最大限度地减少自定义内核中的 for 循环数?

【问题讨论】:

  • 这似乎是两个完全不相关的问题——一个与稀疏矩阵格式转换有关,另一个与 CUDA 编程问题有关。是哪个?
  • 第二个。因为我可能最终会使用三元组格式或三个数组来表示 row_indices、col_indices 和 values。因为我无法找到获取“CSR”格式的 row_ptrs 的方法...... .
  • CUSPARSE 怎么样?它具有转换例程,包括您所询问的例程,以及全面的稀疏 BLAS 操作,所有这些都无需您编写一行代码。它随 CUDA 一起提供,所以你已经拥有了它......
  • @talonmies ....是的,我知道 CUSPARSE 和 CUSP,我也知道使用库总是一个更好的选择,但是,我想知道它是否有效在CUDA中为稀疏矩阵加法/乘法编写我自己的内核...感谢有关cuSPARSE中转换例程的信息...虽然没有从CSC到CSR的方向转换...我必须创建一个中间密集矩阵对于那部分......

标签: matlab cuda sparse-matrix mex


【解决方案1】:

压缩行存储类似于压缩列存储,只是转置了。所以最简单的方法是在将矩阵传递给 MEX 文件之前使用 MATLAB 对其进行转置。然后,使用函数

Ap = mxGetJc(spA);
Ai = mxGetIr(spA);
Ax = mxGetPr(spA);

获取内部指针并将它们视为行存储。 Ap 是行指针,Ai 是非零条目的列索引,Ax 是非零值。请注意,对于对称矩阵,您根本不需要做任何事情! CSC 和 CSR 是一样的。

使用哪种格式很大程度上取决于您以后要对矩阵做什么。例如,查看matrix formats 的稀疏矩阵向量乘法。那是经典论文之一,从那时起研究已经转移,因此您可以进一步环顾四周。

【讨论】:

  • @angainor....感谢您的建议....我能够使用 CUDA CUSP 库从 CSC 转换为 CSR...
  • 也许可以将其作为答案发布,@abhinole。
【解决方案2】:

我最终使用 CUSP 库将 CSC 格式从 Matlab 转换为 CSR,如下所示。

在从 matlab 获取矩阵 A 后,我得到了它的 rowcolvalues 向量,然后我将它们复制到为它们各自创建的 thrust::host_vector 中。

之后我创建了两个cusp::array1d 类型为IndicesValues,如下所示。

    typedef typename cusp::array1d<int,cusp::host_memory>Indices;   
    typedef typename cusp::array1d<float,cusp::host_memory>Values;
    Indices row_indices(rows.begin(),rows.end());
    Indices col_indices(cols.begin(),cols.end());
    Values  Vals(Val.begin(),Val.end());

rowscolsVal 是我从 Matlab 获得的 thrust::host_vector

之后我创建了一个cusp::coo_matrix_view,如下所示。

typedef cusp::coo_matrix_view<Indices,Indices,Values>HostView;
HostView Ah(m,n,NNZa,row_indices,col_indices,Vals);

其中mnNNZa 是我从稀疏矩阵的mex 函数中得到的参数。

我将此视图矩阵复制到设备内存中的cusp::csr_matrix,并设置了正确的尺寸,如下所示。

    cusp::csr_matrix<int,float,cusp::device_memory>CSR(m,n,NNZa);
    CSR = Ah;   

之后,我只是使用 thrust::raw_pointer_cast 将此 CSR 矩阵的三个单独的内容数组复制回主机,其中具有适当维度的数组已经是 mxCalloced,如下所示。

 cudaMemcpy(Acol,thrust::raw_pointer_cast(&CSR.column_indices[0]),sizeof(int)*(NNZa),cudaMemcpyDeviceToHost);
 cudaMemcpy(Aptr,thrust::raw_pointer_cast(&CSR.row_offsets[0]),sizeof(int)*(n+1),cudaMemcpyDeviceToHost);
 cudaMemcpy(Aval,thrust::raw_pointer_cast(&CSR.values[0]),sizeof(float)*(NNZa),cudaMemcpyDeviceToHost);

希望这对使用CUSPMatlab 的人有用

【讨论】:

    【解决方案3】:

    你可以这样做:

    n = size(M,1);
    nz_num = nnz(M);
    [col,rowi,vals] = find(M');
    row = zeros(n+1,1);
    ll = 1; row(1) = 1;
    for l = 2:n
        if rowi(l)~=rowi(l-1)
            ll = ll + 1;
            row(ll) = l;
        end
    end
    row(n+1) = nz_num+1;`
    

    它对我有用,希望它可以帮助别人!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      • 2012-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多