QT 调用 CUDA实现GPU加速图像处理(chapter1)

最近公司项目有个关于图像处理加速的模块,一开始使用的是多线程将图片分批次处理,但是每个图片处理的速度为1s,就算使用多线程,结果还是不达预期。所以这边文章旨在探究GPU加速是否可行以及记录步骤。

如何在QT里面使用CUDA加速,目前看到有两种,
第一种是创建VS+QT项目文件,并在该项目中创建cu文件,编写cuda函数,并于调用。
第二种是自己手动创建动态链接库(DLL), 封装好头文件和lib文件,然后将其导入到QT项目中。

第一种方法据说实现更为简单,但是没有实现过,第二种方法,配置和使用难度稍微较大,但是方便后续大项目的修改以及自己学习,基础的配置和调用一个下午应该就可以调试好,但是具体代码还需要自己另外编写调试。

本次项目考虑到后续的算法修改,采用的第二种。这篇博客详细的介绍了如何从0搭建项目,导出dll文件以及如何调用,也借鉴了很多其他大佬博客。

一:如何生成DLL文件以及lib

1.在VS里面创建新项目,选择DLL(动态链接库),之后选择一个地址创建新项目。

在这里插入图片描述

2. 之后在头文件中新建imageProcess.h 文件,本人经验最好与项目名字一样。

3. 接着在资源文件中新建kernel.cu文件,文件名字任意,后缀名是CU就行。

4. 然后开始配置环节,首先将编译器平台改为debug模式的x64。

请添加图片描述

5. 右击项目找到生成依赖项,选择生成自定义,选择自己电脑里对用的CUDA版本。

请添加图片描述
在这里插入图片描述

6.打开kernel.cu文件右击,选择属性 并改为为下图。

在这里插入图片描述

7. 右击项目属性,找到linker->Input->Additional Dependencies添加cudart.lib并保存。

在这里插入图片描述

8.至此,基本的CUDA环境已经配置好了,接下来分享一下简单的调用代码。

头文件imageProcess.h代码

#pragma once

extern "C" __declspec(dllexport)  int vectorAdd(int c[], int a[], int b[], int size);

kernel.cu代码


#include "cuda_runtime.h";
#include "device_launch_parameters.h";
#include "imageProcess.h";

//#include <opencv2/opencv.hpp>
#include <cfloat>
#include <stdio.h>


__global__ void addKernel(int* c, const int* a, const int* b)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}


int main()
{
    const int arraySize = 5;
    int a[arraySize] = { 1, 2, 3, 4, 5 };
    int b[arraySize] = { 10, 20, 30, 40, 50 };
    int c[arraySize] = { 0 };

    // Add vectors in parallel.
    int result = vectorAdd(c, a, b, arraySize);

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);



    return 0;
}

int vectorAdd(int c[], int a[], int b[], int size)
{
    int result = -1;
    int* dev_a = 0;
    int* dev_b = 0;
    int* dev_c = 0;
    cudaError_t cudaStatus;

    // 选择用于运行的GPU  
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        result = 1;
        goto Error;
    }

    // 在GPU中为变量dev_a、dev_b、dev_c分配内存空间.  
    cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        result = 2;
        goto Error;
    }
    cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        result = 3;
        goto Error;
    }
    cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        result = 4;
        goto Error;
    }

    // 从主机内存复制数据到GPU内存中.  
    cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        result = 5;
        goto Error;
    }
    cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        result = 6;
        goto Error;
    }

    // 启动GPU内核函数  
    addKernel << <1, size >> > (dev_c, dev_a, dev_b);

    // 采用cudaDeviceSynchronize等待GPU内核函数执行完成并且返回遇到的任何错误信息  
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess) {
        result = 7;
        goto Error;
    }

    // 从GPU内存中复制数据到主机内存中  
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        result = 8;
        goto Error;
    }

    result = 0;

    // 重置CUDA设备,在退出之前必须调用cudaDeviceReset  
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        return 9;
    }
Error:
    //释放设备中变量所占内存  
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);

    return result;

}

9. 最后右击生成

在这里插入图片描述

10. 定位到项目文件夹下,找到头文件,dll和.lib文件。

在这里插入图片描述
找到imageProcess的头文件(下图第四个)
www

二:在QT Creator如何调用动态链接库。

1.假设已经创建好QT项目,并且之前的能够运行。右击项目点击添加库,在此之前,最好可以把之前找到的三个文件给提取出来。选择外部库。定位到lib库所在的位置,然后点击下一步即可,pro文件会自动加载配置。

2. 将之前的头文件拷贝到当前项目的头文件目录下,检查pro文件是否配置好。最后一步调试,引入对应的头文件。调用方法。

在这里插入图片描述
结果如下:
在这里插入图片描述

总结:

至此,QT调用CUDA文件的简单步骤已经完成,具体需求代码可以自己填写。
下一章等到完成使用OpenCV完成图像处理后在进行更新。

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值