VS封装CUDA动态库以及QT调用

3 篇文章 0 订阅

我用的是VS2017,QT5.12.3以及Qt Creator4.9.0

1.首先建立VS工程,选择动态链接库
在这里插入图片描述
2.添加cu文件,点击项目名称,选择添加

在这里插入图片描述
然后选择添加cu文件
在这里插入图片描述
3. 写入代码,很简单的向量加法
kernel.cu

#include "cuda_runtime.h"  
#include "device_launch_parameters.h"    
#include "cudadd.h"


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


//向量相加  
CUDADD_API 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;

}

cudadd.h

#pragma once
#ifdef CUDADD_EXPORTS
#define CUDADD_API __declspec(dllexport)
#else
#define CUDADD_API __declspec(dllimport)
#endif

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

4.修改项目的自定义方式为:CUDA10.1
在这里插入图片描述
在这里插入图片描述
5. 修改cu文件的项类型,右键点击cu文件选择“属性”
在这里插入图片描述
6、添加链接器的附加依赖项 cudart.lib
在这里插入图片描述
6. 生成
在这里插入图片描述
此时我们看到debug目录下多出了dll和lib文件
在这里插入图片描述
7. 打开QT Creator,新建一个项目
在这里插入图片描述
建好后右键点击项目,选择“添加库”
在这里插入图片描述
选择“外部库”
在这里插入图片描述
找到刚才生成的lib文件
在这里插入图片描述
在这里插入图片描述
8.将头文件cudadd.h拷到目录下,并添加进工程
在这里插入图片描述
9.在QT项目中main.cpp写入测试代码
main.cpp

#include <QCoreApplication>
#include <iostream>
#include "cudadd.h"

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication e(argc, argv);



    int a[5] = {1,2,3,4,5};
    int b[5] = {3,4,2,3,5};
    int c[5];
    vectorAdd(c,a,b,5);
    cout << a[0] << ' ' << a[1] << ' ' << a[2] << ' ' << a[3] << ' ' << a[4] << endl;
    cout << b[0] << ' ' << b[1] << ' ' << b[2] << ' ' << b[3] << ' ' << b[4] << endl;
    cout << c[0] << ' ' << c[1] << ' ' << c[2] << ' ' << c[3] << ' ' << c[4] << endl;

    return e.exec();
}

10.运行,结果无误,大功告成
在这里插入图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 创建CUDA工程并编写CUDA函数代码 首先需要创建一个CUDA工程,并编写CUDA函数代码。在编写代码时,需要注意以下几点: - 将CUDA函数声明为 extern "C",这样可以保证符号名不会被C++编译器修改。 - 在函数中使用 __global__ 或 __device__ 修饰符,以标记该函数为CUDA函数。 下面是一个简单的例子: ```c extern "C" __global__ void add(int *a, int *b, int *c, int n) { int tid = blockIdx.x * blockDim.x + threadIdx.x; if (tid < n) { c[tid] = a[tid] + b[tid]; } } ``` 2. 编译CUDA代码为动态库 接下来需要将CUDA代码编译为动态库,以便其他程序可以调用其中的函数。可以使用以下命令编译: ``` nvcc -arch=sm_35 -shared -o libcuda.so add.cu ``` 其中,-arch=sm_35 表示编译针对的CUDA架构为sm_35,-shared 表示编译为动态库,-o libcuda.so 表示输出文件名为libcuda.so,add.cu 是要编译的CUDA源文件。 3. 使用动态库中的函数 最后,可以在其他程序中使用该动态库中的函数。在C++程序中,可以使用以下代码调用动态库中的函数: ```c++ #include <iostream> #include <dlfcn.h> typedef void (*AddFunc)(int *, int *, int *, int); int main() { void *handle = dlopen("./libcuda.so", RTLD_LAZY); if (!handle) { std::cerr << "Failed to open library: " << dlerror() << std::endl; return 1; } AddFunc add = reinterpret_cast<AddFunc>(dlsym(handle, "add")); if (!add) { std::cerr << "Failed to find symbol: " << dlerror() << std::endl; dlclose(handle); return 1; } int n = 1024; int *a = new int[n]; int *b = new int[n]; int *c = new int[n]; for (int i = 0; i < n; ++i) { a[i] = i; b[i] = n - i; } add<<<(n+255)/256, 256>>>(a, b, c, n); cudaDeviceSynchronize(); for (int i = 0; i < n; ++i) { std::cout << c[i] << " "; } std::cout << std::endl; delete []a; delete []b; delete []c; dlclose(handle); return 0; } ``` 在上面的代码中,使用 dlopen 函数打开动态库,使用 dlsym 函数查找动态库中的符号(即函数),然后将其转化为函数指针并调用。注意需要在程序中链接 libdl 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值