darknet预测分类性能提升2.1:GPU加速convert_to_image()

更多文章参考:自己动手实现darknet预测分类动态库

1.convet_to_image代码如下:

image convert_to_image(unsigned char* data,int w,int h,int c)
{
	
	int i, j, k;
	image im = make_image(w, h, c);
	for (k = 0; k < c; ++k) {
		for (j = 0; j < h; ++j) {
			for (i = 0; i < w; ++i) {
				int dst_index = i + w*j + w*h*k;
				int src_index = k + c*i + c*w*j;
				im.data[dst_index] = (float)data[src_index] / 255.;
				//printf("c:%d,h:%d,w:%d,src_index:%d,dst_index:%d\n", k, j, i, src_index, dst_index);
			}
		}
	}
	//free(data);
	return im;
}

GPU加速代码:

新建loadimage.cu文件,

添加代码

#include "dark_cuda.h"

//image convert_to_image_gpu(unsigned char* data,int w,int h,int c);
//__global__ void MatConvertImg(float* dst, unsigned char* src, int w,int h,int c) ;
// Kernel定义
__global__ void MatConvertImg(float* dst, unsigned char* src, int w,int h,int c) 
{ 
    int i = blockIdx.x * blockDim.x + threadIdx.x; 
    int j = blockIdx.y * blockDim.y + threadIdx.y; 
	int k = blockIdx.z * blockDim.z + threadIdx.z;
    if (i<w&&j<h&&k<c) 
	{
	   int dst_index = i + w*j + w*h*k;
	   int src_index = k + c*i + c*w*j;
	   dst[dst_index] = (float)src[src_index] / 255.;
	}
      
}

extern "C" image convert_to_image_gpu(unsigned char* data,int w,int h,int c)
{
    int nBytes = w*h*c*sizeof(unsigned char);   
	unsigned char* src;
    cudaMalloc((void**)&src, nBytes);
	float *dst;
    cudaMalloc((void**)&dst, w*h*c*sizeof(float));
	// 将host数据拷贝到device
	//cuda_push_array(src,data,nBytes);  
    cudaError_t status = cudaMemcpyAsync(src, data, nBytes, cudaMemcpyHostToDevice, get_cuda_stream());
    CHECK_CUDA(status);

	// 定义kernel的执行配置
    dim3 blockSize(32,32,1);
    dim3 gridSize((w + blockSize.x - 1) / blockSize.x,(h + blockSize.y - 1) / blockSize.y,(c + blockSize.z - 1) / blockSize.z);
	MatConvertImg << < gridSize, blockSize >>>(dst,src,w,h,c);
	image im = make_image(w, h, c);
	cuda_pull_array(dst,im.data,w*h*c*sizeof(float));
	cudaFree(src);
	cudaFree(dst);

	return im;

}

convert_to_image_gpu函数前一定要加extern "c",否则在c文件中调用convert_to_image_gpu时会发生链接错误。

调用时报错:

关于C语言中的Debug Assertion Failed,在编译和运行时都不会出现错误,但是在执行时会出现错误。发生这种错误的原因可能是:

1、直接释放了一个空指针;

2、一个指针被释放了两次(即第二次释放一个空指针);

3、数组越界:访问了超过数组长度的内存。

跟踪代码发现,程序死在

cuda_pull_array(dst,im.data,w*h*c*sizeof(float));

改成

cuda_pull_array(dst,im.data,w*h*c);

问题解决。

darknet源码解析:cuda_push_array可知,cuda_push_array函数中已经包含sizeof(float)计算,传参只需传入float变量个数就可以了,否则会发生访问越界错误。

 

发布了373 篇原创文章 · 获赞 151 · 访问量 33万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章