A^TA
cuSparseを使用して計算しようとしています。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;
}
私は何が間違っているのですか?
簡単な例を作ろうとしたので、あなたは単に一歩を忘れました。ドキュメントには記載されています。
cuSPARSEライブラリは、スパース行列を完成させるために2段階のアプローチを採用しています。最初のステップでは、ユーザー
csrRowPtrC
はm+1
要素を割り当て、関数cusparseXcsrgemmNnz()
を使用してcsrRowPtrC
非ゼロ要素の総数を決定します。
あなたがしたことはm+1
(m=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]
コメントを追加