CUDA C编程指南矩阵乘法结果中的错误示例
我正在做《CUDA C编程指南》第35页中的矩阵乘法示例,为了练习,我复制了代码并完成了缺失的代码。我理解程序的逻辑和它应该如何工作,但我没有得到预期的结果 这是我制作的完整代码,我不知道错误是我的还是来自示例 守则: 程序编译并运行,但结果矩阵C.元素来自:cudaMemcpyC.元素、d_C.元素、大小、cudaMemcpyDeviceToHost; 是一个随机数。我试着把它当作指向数组的指针来使用,但我没有从中得到任何东西,把它当作数组来处理也不起作用 如果有人能帮我完成这件事,我会很高兴的 首先,请参阅,了解如何获得问题的有用答案。特别是,您应该始终检查CUDAAPI调用和内核启动的返回值。此外,运行cuda memcheck通常可以非常有助于检测像这样的越界访问 @哈里斯问你怎么知道结果是错的,因为你似乎什么都没做 但更重要的是,您有一个16x16线程块来计算15x15矩阵,但您没有注意禁用越界线程。由于您正在尝试创建一个简单的示例,只需将矩阵大小增加到16x16即可-如果您想要处理奇数大小,则需要实现控制逻辑或使用cuBLAS 首先,请参阅,了解如何获得问题的有用答案。特别是,您应该始终检查CUDAAPI调用和内核启动的返回值。此外,运行cuda memcheck通常可以非常有助于检测像这样的越界访问 @哈里斯问你怎么知道结果是错的,因为你似乎什么都没做CUDA C编程指南矩阵乘法结果中的错误示例,cuda,gpgpu,matrix-multiplication,Cuda,Gpgpu,Matrix Multiplication,我正在做《CUDA C编程指南》第35页中的矩阵乘法示例,为了练习,我复制了代码并完成了缺失的代码。我理解程序的逻辑和它应该如何工作,但我没有得到预期的结果 这是我制作的完整代码,我不知道错误是我的还是来自示例 守则: 程序编译并运行,但结果矩阵C.元素来自:cudaMemcpyC.元素、d_C.元素、大小、cudaMemcpyDeviceToHost; 是一个随机数。我试着把它当作指向数组的指针来使用,但我没有从中得到任何东西,把它当作数组来处理也不起作用 如果有人能帮我完成这件事,我会很高
但更重要的是,您有一个16x16线程块来计算15x15矩阵,但您没有注意禁用越界线程。由于您正在尝试创建一个简单的示例,只需将矩阵大小增加到16x16即可-如果您想要处理奇数大小,则需要实现控制逻辑或使用cuBLAS 您的代码在内核中的数组索引和CPU上的初始化之间有轻微的不匹配。下面是@harrism建议的带调试的更正代码:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h>
#include <stdio.h>
using namespace std;
#define BLOCK_SIZE 16
typedef struct
{
int width;
int height;
float *elements;
}Matrix;
__global__ void MatMulKernel(const Matrix,const Matrix, Matrix C);
void MatMul(const Matrix A,const Matrix B, Matrix C)
{
size_t size;
//Matrix A creation y storage in device memory
Matrix d_A;
d_A.width=A.width;
d_A.height=A.height;
size=A.height*A.width*sizeof(float);
cudaMalloc(&d_A.elements,size);
cudaMemcpy(d_A.elements,A.elements,size,cudaMemcpyHostToDevice);
//Matrix B creation y storage in device memory
Matrix d_B;
d_B.width=B.width;
d_B.height=B.height;
size=B.height*B.width*sizeof(float);
cudaMalloc(&d_B.elements,size);
cudaMemcpy(d_B.elements,B.elements,size,cudaMemcpyHostToDevice);
//Matrix C creation y storage in device memory
Matrix d_C;
d_C.width=C.width;
d_C.height=C.height;
//cudaMalloc(&d_C,sizeof(Matrix));
//cudaMemcpy(d_C,C,sizeof(Matrix),cudaMemcpyHostToDevice);
size=C.height*C.width*sizeof(float);
cudaMalloc(&d_C.elements,size);
//
dim3 dimBlock(BLOCK_SIZE,BLOCK_SIZE);
dim3 dimGrid(B.width/dimBlock.x,A.height/dimBlock.y);
MatMulKernel<<<dimGrid,dimBlock>>>(d_A,d_B,d_C);
//Copy the result in the matrix C from the device to the host.
printf("error code: %s\n",cudaGetErrorString(cudaGetLastError()));
cudaMemcpy(C.elements,d_C.elements,size,cudaMemcpyDeviceToHost);
//
cudaFree(d_A.elements);
cudaFree(d_B.elements);
cudaFree(d_C.elements);
}
__global__ void MatMulKernel(Matrix A, Matrix B, Matrix C)
{
//printf("%d\n",threadIdx.x);
float Cvalue=0;
int row=blockIdx.y*blockDim.y+threadIdx.y;
int col=blockIdx.x*blockDim.x+threadIdx.x;
for(int e=0;e<A.width;++e)
{
Cvalue+=A.elements[row*A.width+e]*B.elements[e*B.width+col];
}
C.elements[row*C.width+col]=Cvalue;
}
int print_matrix(Matrix A){
printf("Matrix:\n");
int i;
for(i=0; i<A.width*A.height; i++){
if(i%A.width==0) printf("\n");
printf("%6.4f\t",A.elements[i]);
}
printf("\n");
}
int main()
{
cout<<"Matrices"<<endl;
//Declarationd of the A,B,C matrix.s
float a[BLOCK_SIZE][BLOCK_SIZE];
float b[BLOCK_SIZE][BLOCK_SIZE];
float c[BLOCK_SIZE][BLOCK_SIZE];
//Fill the matrix whit some numbers.
int cont0=0;
for(int c=0;c<BLOCK_SIZE;c++)
{
for(int v=0;v<BLOCK_SIZE;v++)
{
a[v][c]=cont0;
b[v][c]=cont0;
cont0++;
}
}
//Flatten the matrix for the passing to the kernel
int offset=0;
float a_t[BLOCK_SIZE*BLOCK_SIZE];
float b_t[BLOCK_SIZE*BLOCK_SIZE];
for(int y=0;y<BLOCK_SIZE;y++)
{
for(int x=0;x<BLOCK_SIZE;x++)
{
a_t[x+offset]=a[x][y];
b_t[x+offset]=a[x][y];
}
offset=offset+BLOCK_SIZE;
}
float t_C[BLOCK_SIZE*BLOCK_SIZE];
//Completing the matrix format for the kernel.
Matrix m_A;
m_A.height=BLOCK_SIZE;
m_A.width=BLOCK_SIZE;
m_A.elements=a_t;
Matrix m_B;
m_B.height=BLOCK_SIZE;
m_B.width=BLOCK_SIZE;
m_B.elements=b_t;
Matrix m_C;
m_C.height=BLOCK_SIZE;
m_C.width=BLOCK_SIZE;
m_C.elements=t_C;
//Passing the formated matrix to the kernel.
print_matrix(m_A);
print_matrix(m_B);
MatMul(m_A,m_B,m_C);
print_matrix(m_C);
cout<<"Final"<<endl;
return 0;
}
检查输出。如果您看到结果是错误的,请检查输出中报告的系统内核错误。您的代码在内核中的数组索引和CPU上的初始化之间有轻微的不匹配。下面是@harrism建议的带调试的更正代码:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h>
#include <stdio.h>
using namespace std;
#define BLOCK_SIZE 16
typedef struct
{
int width;
int height;
float *elements;
}Matrix;
__global__ void MatMulKernel(const Matrix,const Matrix, Matrix C);
void MatMul(const Matrix A,const Matrix B, Matrix C)
{
size_t size;
//Matrix A creation y storage in device memory
Matrix d_A;
d_A.width=A.width;
d_A.height=A.height;
size=A.height*A.width*sizeof(float);
cudaMalloc(&d_A.elements,size);
cudaMemcpy(d_A.elements,A.elements,size,cudaMemcpyHostToDevice);
//Matrix B creation y storage in device memory
Matrix d_B;
d_B.width=B.width;
d_B.height=B.height;
size=B.height*B.width*sizeof(float);
cudaMalloc(&d_B.elements,size);
cudaMemcpy(d_B.elements,B.elements,size,cudaMemcpyHostToDevice);
//Matrix C creation y storage in device memory
Matrix d_C;
d_C.width=C.width;
d_C.height=C.height;
//cudaMalloc(&d_C,sizeof(Matrix));
//cudaMemcpy(d_C,C,sizeof(Matrix),cudaMemcpyHostToDevice);
size=C.height*C.width*sizeof(float);
cudaMalloc(&d_C.elements,size);
//
dim3 dimBlock(BLOCK_SIZE,BLOCK_SIZE);
dim3 dimGrid(B.width/dimBlock.x,A.height/dimBlock.y);
MatMulKernel<<<dimGrid,dimBlock>>>(d_A,d_B,d_C);
//Copy the result in the matrix C from the device to the host.
printf("error code: %s\n",cudaGetErrorString(cudaGetLastError()));
cudaMemcpy(C.elements,d_C.elements,size,cudaMemcpyDeviceToHost);
//
cudaFree(d_A.elements);
cudaFree(d_B.elements);
cudaFree(d_C.elements);
}
__global__ void MatMulKernel(Matrix A, Matrix B, Matrix C)
{
//printf("%d\n",threadIdx.x);
float Cvalue=0;
int row=blockIdx.y*blockDim.y+threadIdx.y;
int col=blockIdx.x*blockDim.x+threadIdx.x;
for(int e=0;e<A.width;++e)
{
Cvalue+=A.elements[row*A.width+e]*B.elements[e*B.width+col];
}
C.elements[row*C.width+col]=Cvalue;
}
int print_matrix(Matrix A){
printf("Matrix:\n");
int i;
for(i=0; i<A.width*A.height; i++){
if(i%A.width==0) printf("\n");
printf("%6.4f\t",A.elements[i]);
}
printf("\n");
}
int main()
{
cout<<"Matrices"<<endl;
//Declarationd of the A,B,C matrix.s
float a[BLOCK_SIZE][BLOCK_SIZE];
float b[BLOCK_SIZE][BLOCK_SIZE];
float c[BLOCK_SIZE][BLOCK_SIZE];
//Fill the matrix whit some numbers.
int cont0=0;
for(int c=0;c<BLOCK_SIZE;c++)
{
for(int v=0;v<BLOCK_SIZE;v++)
{
a[v][c]=cont0;
b[v][c]=cont0;
cont0++;
}
}
//Flatten the matrix for the passing to the kernel
int offset=0;
float a_t[BLOCK_SIZE*BLOCK_SIZE];
float b_t[BLOCK_SIZE*BLOCK_SIZE];
for(int y=0;y<BLOCK_SIZE;y++)
{
for(int x=0;x<BLOCK_SIZE;x++)
{
a_t[x+offset]=a[x][y];
b_t[x+offset]=a[x][y];
}
offset=offset+BLOCK_SIZE;
}
float t_C[BLOCK_SIZE*BLOCK_SIZE];
//Completing the matrix format for the kernel.
Matrix m_A;
m_A.height=BLOCK_SIZE;
m_A.width=BLOCK_SIZE;
m_A.elements=a_t;
Matrix m_B;
m_B.height=BLOCK_SIZE;
m_B.width=BLOCK_SIZE;
m_B.elements=b_t;
Matrix m_C;
m_C.height=BLOCK_SIZE;
m_C.width=BLOCK_SIZE;
m_C.elements=t_C;
//Passing the formated matrix to the kernel.
print_matrix(m_A);
print_matrix(m_B);
MatMul(m_A,m_B,m_C);
print_matrix(m_C);
cout<<"Final"<<endl;
return 0;
}
检查输出。如果您看到结果是错误的,请检查输出中报告的系统内核错误。您的代码没有对复制回m_C的结果执行任何操作,那么您如何知道结果是错误的?你写了打印出来的代码吗?对不起,你是对的,我发布了干净版本的代码,我在cudaMemcpyC.elements,d_C.elements,size,cudaMemcpyDeviceToHost中使用了断点;而一个用于打印CYour代码元素的方法并没有对复制回m_C的结果做任何事情,那么你怎么知道结果是错误的呢?你写了打印出来的代码吗?对不起,你是对的,我发布了干净版本的代码,我在cudaMemcpyC.elements,d_C.elements,size,cudaMemcpyDeviceToHost中使用了断点;为了打印CMy错误的元素,我在发布前清理注释代码和未使用的代码,我使用breackpoint和FOR循环打印MatMul中C.元素的内容。我的错误,我在发布前清理注释代码和未使用的代码,我使用breackpoint和FOR循环打印C的内容。MatMul.t_C中的元素应该是size BLOCK_size*BLOCK_size,除非我读错了。不过做得好,+1.t_C应该是块大小*块大小,除非我读错了。干得好,+1。