在输出中混合推力和 cuBLAS 意外结果
Mixing Thrust and cuBLAS unexpected results in output
我喜欢 thrust 库,尤其是它如何很好地隐藏 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 内存中,因此不显示地址内的数据。
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
"vector" 最初包含垃圾。如果您将 beta
设置为零,则没有关系。但是由于你的 beta
设置为 1,所以这个未初始化区域的内容被添加到你的结果向量中。
如果你设置
float bet = 0.0f;
我想你会得到预期的结果(我这样做了,有了这个改变。)
关于这个问题:
And secondly is there anyway to check forexample "float* device2DMatrixPtr" with debugger?
您可以使用例如打印出 deviceT2DMatrix
值printf
或 std::cout
。 Thrust 将为您复制值 device->host "under the hood",以方便执行此操作。如果要在调试器中访问设备副本,请在 windows 上使用 nsight VSE 的设备调试功能,或者在 linux
上使用 nsight EE 或 cuda-gdb
我喜欢 thrust 库,尤其是它如何很好地隐藏 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 内存中,因此不显示地址内的数据。
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
"vector" 最初包含垃圾。如果您将 beta
设置为零,则没有关系。但是由于你的 beta
设置为 1,所以这个未初始化区域的内容被添加到你的结果向量中。
如果你设置
float bet = 0.0f;
我想你会得到预期的结果(我这样做了,有了这个改变。)
关于这个问题:
And secondly is there anyway to check forexample "float* device2DMatrixPtr" with debugger?
您可以使用例如打印出 deviceT2DMatrix
值printf
或 std::cout
。 Thrust 将为您复制值 device->host "under the hood",以方便执行此操作。如果要在调试器中访问设备副本,请在 windows 上使用 nsight VSE 的设备调试功能,或者在 linux