【问题标题】:Mixing Thrust and cuBLAS unexpected results in output混合 Thrust 和 cuBLAS 出乎意料的输出结果
【发布时间】:2015-11-16 22:43:33
【问题描述】:

我喜欢推力库,尤其是它如何很好地隐藏 cudaMalloc、cudaFree 等的复杂性。

我想对矩阵的所有列求和。所以我使用了 cuBlas 的“cublasSgemv”并将我的矩阵乘以一个向量。这是我的代码:

void sEarColSum(std::vector<float>& inMatrix, int colSize)
{
    cublasHandle_t handle; // CUBLAS context
    float al = 1.0f; // al =1
    float bet = 1.0f; // bet =1
    int rowSize = inMatrix.size() / colSize;

    float *devOutputPtr = thrust::raw_pointer_cast(thrust::device_malloc<float>(colSize));

    thrust::device_vector<float> deviceT2DMatrix(inMatrix.begin(), inMatrix.end());
    float* device2DMatrixPtr = thrust::raw_pointer_cast(deviceT2DMatrix.data());

    thrust::device_vector<float> deviceVector(rowSize, 1.0f);
    float* deviceVecPtr = thrust::raw_pointer_cast(deviceVector.data());

    cublasCreate(&handle);
    cublasSgemv(handle, CUBLAS_OP_N, colSize, rowSize, &al, device2DMatrixPtr, colSize, deviceVecPtr, 1, &bet, devOutputPtr, 1);

    std::vector<float> outputVec(colSize);
    cudaMemcpy(outputVec.data(), devOutputPtr, outputVec.size() * sizeof(float), cudaMemcpyDeviceToHost);

    for (auto elem : outputVec)
        std::cout << elem << std::endl;
}



int main(void)
{
    std::vector < float > temp(100, 1); // A vector of 100 elements each 1 
    sEarColSum( temp, 10 ); // Means my vector will have 10 columns and 100/10 = 10 rows  
  //so I expect a output vector with 10 elements. Which all elements have the value of 10. 
}

不幸的是,结果只是垃圾。我期待一个包含十个元素的向量,每个值都是十。但相反,我得到的是:

30
30
-2.80392e+036
30
30
-4.95176e+029
30
6.64319e+016
-3.72391e+037
30

我是否遗漏了什么,我的代码哪里出错了?
其次,有没有用调试器检查例如“float * device2DMatrixPtr”? Visual Studio 显示它的地址,但由于它位于 GPU 内存中,它不会显示地址内部的数据。

【问题讨论】:

    标签: c++ cuda thrust cublas


    【解决方案1】:

    cublas 函数gemv 执行matrix-vector product

    y = alpha*A*x + beta*y
    

    上述等式中的y 由您分配的devOutputPtr 表示,如下所示:

    float *devOutputPtr = thrust::raw_pointer_cast(thrust::device_malloc<float>(colSize));
    

    这样的普通推力分配:

    thrust::device_vector<float> my_vec...
    

    将分配并初始化存储空间,但thrust::device_malloc 只分配存储空间,并没有对其进行初始化。

    因此,您的y“向量”最初包含垃圾。如果您已将beta 设置为零,那么这无关紧要。但是由于您的beta 设置为 1,因此该未初始化区域的内容将添加到您的结果向量中。

    如果你设置了

    float bet = 0.0f;
    

    我想你会得到预期的结果(我会的,有了这个改变。)

    关于这个问题:

    其次,是否可以使用调试器检查例如“float* device2DMatrixPtr”?

    您可以使用例如打印deviceT2DMatrixprintfstd::cout。 Thrust 将为您复制值 device->host “在引擎盖下”,以促进这一点。如果要在调试器中访问设备副本,请使用 windows 上的 nsight VSE 或 linux 上的 nsight EE 或 cuda-gdb 的设备调试功能

    【讨论】:

    • 谢谢!!!!我不明白的一件事,如果内存分配是那么简单的推力,为什么还有人使用带有 6 个参数的 cublasSetMatrix?
    • cublasSetMatrix 不是do allocation。如果你声称(在你的问题中你似乎是这样)这:float *devOutputPtr = thrust::raw_pointer_cast(thrust::device_malloc&lt;float&gt;(colSize)); 比这更简单:float *devOutputPtr; cudaMalloc(&amp;devOutputPtr, colSize*sizeof(float));,那么我不确定我是否同意你的看法。
    • 再次感谢您的评论,我比较的是thrust::device_vector&lt;float&gt; deviceT2DMatrix(inMatrix.begin(), inMatrix.end()); float* device2DMatrixPtr = thrust::raw_pointer_cast(deviceT2DMatrix.data()); vs float * device2DMatrixPtr; cublasSetMatrix(rowSize, colSize, sizeof(float)*inMatrix.size(), inMatrix.data(), rowSize, device2DMatrixPtr, rowSize);
    • 我猜你还是真的不明白cublasSetMatrix不做分配。因此,您的第二个示例无法正常工作。这似乎与您最初的问题大相径庭。如果您认为提出“为什么有人会使用 cublasSetMatrix”是一个重要问题,请将其作为一个新问题提出。
    • 复制 的角度来看,cublasSetMatrix 可以做一些推力不能做的事情,例如在一个更大的矩阵中设置/修改一个子矩阵,该矩阵已经在设备。
    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 2016-09-03
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多