cuSparse(cusparseDcsrgemm)での行列の乗算は、間違った結果を出力します

user3667089

A^TAcuSparseを使用て計算しようとしています。Aは大きいが、スパース行列です。問題は、関数を使用するcusparseDcsrgemmと、計算された出力が間違っていることです。問題を再現するには、以下の最小限の例を参照してください。

CMakeLists.txt

cmake_minimum_required(VERSION 3.11)

project(sample)

find_package(CUDA REQUIRED)

add_executable(${PROJECT_NAME} main.cpp)

target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14)

target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CUDA_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME} ${CUDA_LIBRARIES} ${CUDA_cusparse_LIBRARY})

main.cpp

#include <iostream>
#include <vector>

#include <cuda_runtime_api.h>
#include <cusparse_v2.h>

int main(){
  // 3x3 identity matrix in CSR format
  std::vector<int> row;
  std::vector<int> col;
  std::vector<double> val;

  row.emplace_back(0);
  row.emplace_back(1);
  row.emplace_back(2);
  row.emplace_back(3);

  col.emplace_back(0);
  col.emplace_back(1);
  col.emplace_back(2);

  val.emplace_back(1);
  val.emplace_back(1);
  val.emplace_back(1);

  int *d_row;
  int *d_col;
  double *d_val;

  int *d_out_row;
  int *d_out_col;
  double *d_out_val;

  cudaMalloc(reinterpret_cast<void **>(&d_row), row.size() * sizeof(int));
  cudaMalloc(reinterpret_cast<void **>(&d_col), col.size() * sizeof(int));
  cudaMalloc(reinterpret_cast<void **>(&d_val), val.size() * sizeof(double));

  // we know identity transpose times identity is still identity 
  cudaMalloc(reinterpret_cast<void **>(&d_out_row), row.size() * sizeof(int));
  cudaMalloc(reinterpret_cast<void **>(&d_out_col), col.size() * sizeof(int));
  cudaMalloc(reinterpret_cast<void **>(&d_out_val), val.size() * sizeof(double));

  cudaMemcpy(
      d_row, row.data(), sizeof(int) * row.size(), cudaMemcpyHostToDevice);
  cudaMemcpy(
      d_col, col.data(), sizeof(int) * col.size(), cudaMemcpyHostToDevice);
  cudaMemcpy(
      d_val, val.data(), sizeof(double) * val.size(), cudaMemcpyHostToDevice);

  cusparseHandle_t handle;
  cusparseCreate(&handle);

  cusparseMatDescr_t descr;
  cusparseCreateMatDescr(&descr);
  cusparseSetMatType(descr, CUSPARSE_MATRIX_TYPE_GENERAL);
  cusparseSetMatIndexBase(descr, CUSPARSE_INDEX_BASE_ZERO);

  cusparseMatDescr_t descr_out;
  cusparseCreateMatDescr(&descr_out);
  cusparseSetMatType(descr_out, CUSPARSE_MATRIX_TYPE_GENERAL);
  cusparseSetMatIndexBase(descr_out, CUSPARSE_INDEX_BASE_ZERO);

  cusparseDcsrgemm(handle,
                   CUSPARSE_OPERATION_TRANSPOSE,
                   CUSPARSE_OPERATION_NON_TRANSPOSE,
                   3,
                   3,
                   3,
                   descr,
                   3,
                   d_val,
                   d_row,
                   d_col,
                   descr,
                   3,
                   d_val,
                   d_row,
                   d_col,
                   descr_out,
                   d_out_val,
                   d_out_row,
                   d_out_col);

  cudaMemcpy(
      row.data(), d_out_row, sizeof(int) * row.size(), cudaMemcpyDeviceToHost);
  cudaMemcpy(
      col.data(), d_out_col, sizeof(int) * col.size(), cudaMemcpyDeviceToHost);
  cudaMemcpy(
      val.data(), d_out_val, sizeof(double) * val.size(), cudaMemcpyDeviceToHost);

  std::cout << "row" << std::endl;
  for (int i : row)
  {
    std::cout << i << std::endl; //show 0 0 0 0, but it should be 0 1 2 3
  }

  std::cout << "col" << std::endl;
  for (int i : col)
  {
    std::cout << i << std::endl; //show 1 0 0, but it should be 0 1 2
  }

  std::cout << "val" << std::endl;
  for (int i : val)
  {
    std::cout << i << std::endl; //show 1 0 0, but it should be 1 1 1
  }

  return 0;
}

私は何が間違っているのですか?

BlameTheBits

簡単な例を作ろうとしたので、あなたは単に一歩を忘れました。ドキュメントには記載されています。

cuSPARSEライブラリは、スパース行列を完成させるために2段階のアプローチを採用しています。最初のステップでは、ユーザーcsrRowPtrCm+1要素を割り当て、関数cusparseXcsrgemmNnz()使用してcsrRowPtrC非ゼロ要素の総数を決定します。

あなたがしたことはm+1m=3あなたの例では)要素を割り当てるd_row_outことであり3、あなたあなたの例にある非ゼロ要素の総数を決定しましたしかしd_row_out、ベクトルを正しい値で埋めることを意味する「決定」を実行できませんでした。簡単な例では、行を追加するだけです。

cudaMemcpy(d_out_row, row.data(), sizeof(int) * row.size(), cudaMemcpyHostToDevice);

ジェムコールの前のどこか。

もちろん、より一般的なアプローチは、提案された関数を使用することですcusparseXcsrgemmNnz()gemm呼び出しの前のどこかに次の行を追加できます(多くの値はまだ例のようにハードコードされているため、実際には一般的ではありません)。

int nnz_check[1];
cusparseXcsrgemmNnz(handle,
                    CUSPARSE_OPERATION_TRANSPOSE,
                    CUSPARSE_OPERATION_NON_TRANSPOSE,
                    3,
                    3,
                    3,
                    descr,
                    3,
                    d_row,
                    d_col,
                    descr,
                    3,
                    d_row,
                    d_col,
                    descr_out,
                    d_out_row,  // the values this pointer points to will be set
                    nnz_check); // the number of nonzeros will also be calculated
assert(nnz_check[0] == 3);

補足:ドキュメントには、「[[DEPRECATED]]をcusparse<t>csrgemm2()代わりに使用してください。ルーチンは次のメジャーリリースで削除されます」、つまりバージョン11と記載されています。同じ2段階のアプローチと同じように、2番目のgemmバージョンでも問題が残ります。中古。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Eigenでのスパース行列の乗算は、間違った結果をもたらしますか?

分類Dev

Scipyは行列乗算に対して間違った結果を出します

分類Dev

Python numpy:行列の乗算で間違った結果が得られる

分類Dev

cudaは乗算カウンターで間違った結果を計算します

分類Dev

Pythonの間違った乗算結果

分類Dev

ベクトルによる行列の乗算は間違った答えを返しますJava

分類Dev

誤った結果を生成する配列を使用した行列の乗算

分類Dev

行列乗算の結果は「nan」です

分類Dev

イングレス乗算は間違った結果をもたらします

分類Dev

scipyスパース行列のsklearntrain_test_splitは間違った結果をもたらします

分類Dev

Apache Commons Math:三重対角行列の固有分解は間違った結果をもたらします

分類Dev

DATEのOracleSQL比較は間違った結果を返します

分類Dev

2つの大きな数を乗算すると、間違った結果が得られます

分類Dev

Sparkでの結合は間違った結果を出力しますが、マップ側の結合は正しいです

分類Dev

Cで2つの32ビット数を乗算する間違った結果

分類Dev

SQL Like with wildcardは、特定の文字で間違った結果を返します

分類Dev

uniqueNは、jの条件で間違った結果を返します

分類Dev

SUM(DISTINCT(column))は、特定の条件で間違った結果を返します

分類Dev

SQLクエリの結果が乗算され、間違った結果が表示されます

分類Dev

球の体積を計算した後に間違った結果が出力されました

分類Dev

System.Numericsを使用した行列乗算の値が完全に間違っています

分類Dev

2つの文字のビットごとのANDは、間違った結果を出力します

分類Dev

Longをfloat数に乗算すると、場合によっては間違った結果になります

分類Dev

Oracleの "order by"句は、結果を間違った順序で返すか、結果が欠落しています

分類Dev

Tensorflow:GPUでの行列乗算(NaN)の誤った結果

分類Dev

Cのポインタで正方行列を転置します。間違った出力

分類Dev

C ++ openmp並列計算は間違った結果を計算します

分類Dev

Javaの:組み合わせソート関数は、間違った結果を計算します

分類Dev

私のUDPチェックサム計算は毎回間違った結果を出します

Related 関連記事

  1. 1

    Eigenでのスパース行列の乗算は、間違った結果をもたらしますか?

  2. 2

    Scipyは行列乗算に対して間違った結果を出します

  3. 3

    Python numpy:行列の乗算で間違った結果が得られる

  4. 4

    cudaは乗算カウンターで間違った結果を計算します

  5. 5

    Pythonの間違った乗算結果

  6. 6

    ベクトルによる行列の乗算は間違った答えを返しますJava

  7. 7

    誤った結果を生成する配列を使用した行列の乗算

  8. 8

    行列乗算の結果は「nan」です

  9. 9

    イングレス乗算は間違った結果をもたらします

  10. 10

    scipyスパース行列のsklearntrain_test_splitは間違った結果をもたらします

  11. 11

    Apache Commons Math:三重対角行列の固有分解は間違った結果をもたらします

  12. 12

    DATEのOracleSQL比較は間違った結果を返します

  13. 13

    2つの大きな数を乗算すると、間違った結果が得られます

  14. 14

    Sparkでの結合は間違った結果を出力しますが、マップ側の結合は正しいです

  15. 15

    Cで2つの32ビット数を乗算する間違った結果

  16. 16

    SQL Like with wildcardは、特定の文字で間違った結果を返します

  17. 17

    uniqueNは、jの条件で間違った結果を返します

  18. 18

    SUM(DISTINCT(column))は、特定の条件で間違った結果を返します

  19. 19

    SQLクエリの結果が乗算され、間違った結果が表示されます

  20. 20

    球の体積を計算した後に間違った結果が出力されました

  21. 21

    System.Numericsを使用した行列乗算の値が完全に間違っています

  22. 22

    2つの文字のビットごとのANDは、間違った結果を出力します

  23. 23

    Longをfloat数に乗算すると、場合によっては間違った結果になります

  24. 24

    Oracleの "order by"句は、結果を間違った順序で返すか、結果が欠落しています

  25. 25

    Tensorflow:GPUでの行列乗算(NaN)の誤った結果

  26. 26

    Cのポインタで正方行列を転置します。間違った出力

  27. 27

    C ++ openmp並列計算は間違った結果を計算します

  28. 28

    Javaの:組み合わせソート関数は、間違った結果を計算します

  29. 29

    私のUDPチェックサム計算は毎回間違った結果を出します

ホットタグ

アーカイブ