一个完整的手工构建的cuda动态链接库工程 03记

1, 源代码

仅仅是加入了模板函数和对应的 .cuh文件,当前的目录结构如下:



icmm/gpu/add.cu

#include <stdio.h>
#include <cuda_runtime.h>#include "inc/add.cuh"// different name in this level for different typename, as extern "C" can not decorate template function that is in C++;extern "C"  void  vector_add_gpu_s(float *A, float *B, float *C, int n)
{dim3 grid, block;block.x = 256;grid.x = (n + block.x - 1) / block.x;printf("CUDA kernel launch with %d blocks of %d threads\n", grid.x, block.x);vector_add_kernel<><<<grid, block>>>(A, B, C, n);
}extern "C"  void  vector_add_gpu_d(double* A, double* B, double* C, int n)
{dim3 grid, block;block.x = 256;grid.x = (n + block.x - 1) / block.x;printf("CUDA kernel launch with %d blocks of %d threads\n", grid.x, block.x);vector_add_kernel<><<<grid, block>>>(A, B, C, n);
}

icmm/gpu/add.h

#pragma onceextern "C"  void  vector_add_gpu_s(float *A, float *B, float *C, int n);
extern "C"  void  vector_add_gpu_d(double* A, double* B, double* C, int n);

icmm/gpu/inc/add.cuh

#pragma oncetemplate<typename T>
__global__ void vector_add_kernel(T *A, T *B, T *C, int n)
{int i = blockDim.x * blockIdx.x + threadIdx.x;if (i < n){C[i] = A[i] + B[i] + 0.0f;}
}

icmm/gpu/inc/sub.cuh

#pragma oncetemplate<typename T>
__global__ void vector_sub_kernel(T *A, T *B, T *C, int n)
{int i = blockDim.x * blockIdx.x + threadIdx.x;if (i < n){C[i] = A[i] - B[i] + 0.0f;}
}

icmm/gpu/sub.cu

#include <stdio.h>
#include <cuda_runtime.h>
#include "inc/sub.cuh"extern "C"  void  vector_sub_gpu_s(float *A, float *B, float *C, int n)
{dim3 grid, block;block.x = 256;grid.x = (n + block.x - 1) / block.x;printf("CUDA kernel launch with %d blocks of %d threads\n", grid.x, block.x);vector_sub_kernel<><<<grid, block>>>(A, B, C, n);
}extern "C"  void  vector_sub_gpu_d(double *A, double *B, double *C, int n)
{dim3 grid, block;block.x = 256;grid.x = (n + block.x - 1) / block.x;printf("CUDA kernel launch with %d blocks of %d threads\n", grid.x, block.x);vector_sub_kernel<><<<grid, block>>>(A, B, C, n);
}

icmm/gpu/sub.h

#pragma onceextern "C"  void  vector_sub_gpu_s(float *A, float *B, float *C, int n);
extern "C"  void  vector_sub_gpu_d(double *A, double *B, double *C, int n);

icmm/include/icmm.h


#pragma once
#include<cuda_runtime.h>void hello_print();
void ic_S_add(float* A, float* B, float *C, int n);
void ic_D_add(double* A, double* B, double* C, int n);void ic_S_sub(float* A, float* B, float *C, int n);
void ic_D_sub(float* A, float* B, float *C, int n);

icmm/Makefile

#libicmm.soTARGETS = libicmm.so
GPU_ARCH= -arch=sm_70all: $(TARGETS)sub.o: gpu/sub.cunvcc    -Xcompiler -fPIC $(GPU_ARCH) -c $<add.o: gpu/add.cunvcc    -Xcompiler -fPIC $(GPU_ARCH) -c $<
#-dc
#-rdc=trueadd_link.o: add.onvcc   -Xcompiler -fPIC  $(GPU_ARCH) -dlink   -o $@  $<  -L/usr/local/cuda/lib64 -lcudart -lcudadevrtic_add.o: src/ic_add.cppg++ -fPIC -c $<  -L/usr/local/cuda/lib64 -I/usr/local/cuda/include -lcudart -lcudadevrt -I./ic_sub.o: src/ic_sub.cppg++ -fPIC -c $<  -L/usr/local/cuda/lib64 -I/usr/local/cuda/include -lcudart -lcudadevrt -I./$(TARGETS): sub.o ic_sub.o add.o ic_add.o add_link.omkdir -p libg++ -shared -fPIC  $^  -o lib/libicmm.so -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lcudart -lcudadevrt -rm -f *.o.PHONY:clean
clean:-rm -f *.o lib/*.so test ./bin/test-rm -rf lib bin

icmm/makefile_bin

# executable
TARGET = test
GPU_ARCH = -arch=sm_70all: $(TARGET)add.o: gpu/add.cunvcc -dc -rdc=true $(GPU_ARCH) -c $<sub.o: gpu/sub.cunvcc -dc -rdc=true $(GPU_ARCH) -c $<add_link.o: add.onvcc $(GPU_ARCH) -dlink   -o $@  $<  -L/usr/local/cuda/lib64 -lcudart -lcudadevrtsub_link.o: sub.onvcc $(GPU_ARCH) -dlink   -o $@  $<  -L/usr/local/cuda/lib64 -lcudart -lcudadevrtic_add.o: src/ic_add.cppg++ -c $<  -L/usr/local/cuda/lib64 -I/usr/local/cuda/include -lcudart -lcudadevrt -I./ic_sub.o: src/ic_sub.cppg++ -c $<  -L/usr/local/cuda/lib64 -I/usr/local/cuda/include -lcudart -lcudadevrt -I./test.o: testing/test.cppg++ -c $< -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lcudart -lcudadevrt -I./includetest: sub.o ic_sub.o sub_link.o add.o ic_add.o test.o add_link.og++ $^ -L/usr/local/cuda/lib64 -lcudart -lcudadevrt   -o testmkdir ./bincp ./test ./bin/-rm -f *.o.PHONY:clean
clean:-rm -f *.o bin/* $(TARGET)

icmm/src/ic_add.cpp

#include <stdio.h>
#include <cuda_runtime.h>
#include "gpu/add.h"
//extern void vector_add_gpu(float *A, float *B, float *C, int n);void hello_print()
{printf("hello world!\n");
}//void ic_add(float* A, float* B, float *C, int n){  vector_add_gpu(A, B, C, n);}
void ic_S_add(float* A, float* B, float *C, int n)
{vector_add_gpu_s(A, B, C, n);
}void ic_D_add(double* A, double* B, double* C, int n)
{vector_add_gpu_d(A, B, C, n);
}

icmm/src/ic_sub.cpp

#include <stdio.h>
#include <cuda_runtime.h>#include "gpu/sub.h"
//extern void vector_add_gpu(float *A, float *B, float *C, int n);
void ic_S_sub(float* A, float* B, float *C, int n)
{vector_sub_gpu_s(A, B, C, n);
}void ic_D_sub(double* A, double* B, double *C, int n)
{vector_sub_gpu_d(A, B, C, n);
}

icmm/testing/Makefile

#testTARGET = testall: $(TARGET)CXX_FLAGS = -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lcudart -lcudadevrt  -I../include -L../test.o: test.cppg++  -c $< $(CXX_FLAGS)$(TARGET):test.og++ $< -o $@ -L/usr/local/cuda/lib64 -lcudart -lcudadevrt  -L../lib  -licmm@echo "to execute: export LD_LIBRARY_PATH=${PWD}/../lib".PHONY:clean
clean:-rm -f *.o $(TARGET)

icmm/testing/test.cpp


#include <cuda_runtime.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>#include "icmm.h"void add_test_s(float* A, float* B, float* C, int n)
{ic_S_add(A, B, C, n);printf("Copy output data from the CUDA device to the host memory\n");float* h_C = (float*)malloc(n*sizeof(float));cudaMemcpy(h_C, C, n*sizeof(float), cudaMemcpyDeviceToHost);for (int i = 0; i < n; ++i){printf("%3.2f ", h_C[i]);// if (fabs(h_A[i] + h_B[i] - h_C[i]) > 1e-5) {      fprintf(stderr, "Result verification failed at element %d!\n", i);      exit(EXIT_FAILURE);    }}printf("\nTest PASSED\n");free(h_C);
}/**/
void add_test_d(double* A, double* B, double* C, int n)
{ic_D_add(A, B, C, n);printf("Copy output data from the CUDA device to the host memory\n");float *h_C = (float *)malloc(n*sizeof(double));cudaMemcpy(h_C, C, sizeof(double), cudaMemcpyDeviceToHost);for (int i = 0; i < n; ++i){printf("%3.2f ", h_C[i]);// if (fabs(h_A[i] + h_B[i] - h_C[i]) > 1e-5) {      fprintf(stderr, "Result verification failed at element %d!\n", i);      exit(EXIT_FAILURE);    }}printf("\nTest PASSED\n");free(h_C);
}/**/
void sub_test_s(float* A, float* B, float* C, int n)
{ic_S_sub(A, B, C, n);printf("Copy output data from the CUDA device to the host memory\n");float* h_C = (float*)malloc(n*sizeof(float));cudaMemcpy(h_C, C, n*sizeof(float), cudaMemcpyDeviceToHost);for (int i = 0; i < n; ++i){printf("%3.2f ", h_C[i]);// if (fabs(h_A[i] + h_B[i] - h_C[i]) > 1e-5) {      fprintf(stderr, "Result verification failed at element %d!\n", i);      exit(EXIT_FAILURE);    }}printf("\nTest PASSED\n");free(h_C);
}int main(void)
{int n = 50;size_t size = n * sizeof(float);float *h_A = (float *)malloc(size);float *h_B = (float *)malloc(size);float *h_C = (float *)malloc(size);for (int i = 0; i < n; ++i){h_A[i] =  rand() / (float)RAND_MAX;h_B[i] =  rand() / (float)RAND_MAX;}float *d_A = NULL;float *d_B = NULL;float *d_C = NULL;cudaMalloc((void **)&d_A, size);cudaMalloc((void **)&d_B, size);cudaMalloc((void **)&d_C, size);cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
/*int threadsPerBlock = 256;int blocksPerGrid = (n + threadsPerBlock - 1) / threadsPerBlock;printf("CUDA kernel launch with %d blocks of %d threads\n", blocksPerGrid, threadsPerBlock);vector_add_kernel<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, n);
*///ic_add(d_A, d_B, d_C, n);add_test_s(d_A, d_B, d_C, n);sub_test_s(d_A, d_B, d_C, n);cudaFree(d_A);cudaFree(d_B);cudaFree(d_C);free(h_A);free(h_B);free(h_C);printf("Done\n");return 0;
}

2. 总结

.cu 代码给 g++ 的 .cpp 的代码需要使用 extern "C" 来修饰,所以一template 函数的实例化不能一直贯彻到 .cu 源代码的最顶层;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/195008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pygame时序模块time

文章目录 简介时钟对象平抛运动 pygame系列&#xff1a;初步&#x1f48e;加载图像&#x1f48e;图像变换&#x1f48e;直线绘制 简介 之前在更新图形的时候&#xff0c;为了调控死循环的响应时间&#xff0c;用到了time.sleep。而实际上&#xff0c;我们并不需要额外导入其他…

Failed to connect to gitee.com port 443: Time out 连接超时提示【Bug已完美解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:解决方案1解决方案2:解决方案3:此Bug解决方案总结解决方案总结**心得体会:解决连接超时问题的三种方案**项目场景: 导入Sample时遇到导入失败的情况,并提示“Failed to connect to gitee.com port 443: Time out”连接超…

YouTube Premium 会员白嫖教程

前言 YouTube是美国Alphabet旗下的视频分享网站&#xff0c;也是目前全球最大的视频搜索和分享平台&#xff0c;同时允许用户上传、观看、分享及评论视频 1、点击自己的头像&#xff0c;点击购买内容与会员 2、点击免费试订 3、这里选择个人 4、点击开始试用一个月 5、添加一…

Git 配置文件(.gitignore)

前言 在使用 Git 分布式版本控制系统的时候&#xff0c;有些文件如&#xff1a;数据库的一些配置文件&#xff0c;我们不想让这类文件在远程仓库让 Git 来管理&#xff0c;不想让别人看到&#xff0c;此时就可以自己在 Git 仓库目录下创建 / 在远程仓库创建的时候就配置好 .git…

uniapp中进行地图定位

目录 一、创建map 二、data中声明变量 三、获取当前位置信息&#xff0c;进行定位 四、在methods中写移动图标获取地名地址的方法 五、最终展示效果 一、创建map <!-- 地图展示 --><view class"mymap"><!-- <view class"mymap__map"…

LangChain(0.0.340)官方文档五:Model

LangChain官网、LangChain官方文档 、langchain Github、langchain API文档、llm-universe 文章目录 一、Chat models1.1 Chat models简介1.2 Chat models的调用方式1.2.1 环境配置1.2.2 使用LCEL方式调用Chat models1.2.3 使用内置Chain调用Chat models 1.3 缓存1.3.1 内存缓存…

如何调用 API | 学习笔记

开发者学堂课程【阿里云 API 网关使用教程:如何调用 API】学习笔记&#xff0c;与课程紧密联系&#xff0c;让用户快速学习知识。 课程地址&#xff1a;阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 如何调用 API 调用 API 的三要素 要调用 API 需要三…

组网技术-交换机

交换机&#xff1a; 分类&#xff1a; 根据交换方式划分&#xff1a; 1.存储转发交换&#xff1a;交换机对输入的数据包先进行缓存、验证、碎片过滤&#xff0c;然后进行转发。 时延大&#xff0c;但是可以提供差错校验&#xff0c;并支持不同速度的输入、输出端口间的交换…

Python读取二进制文件:深入解析与技术实现

目录 一、引言 二、二进制文件的基础 1、二进制文件的组成 2、二进制文件的编码 三、Python读取二进制文件的方法 1、使用内置函数open() 2、使用numpy库 四、处理读取的二进制数据 1、解析数据 2. 转换数据类型 五、总结与展望 1、高效读取二进制文件 2、处理复杂…

ssm医药进出口交易系统源码和论文

ssm医药进出口交易系统源码和论文726 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构…

电源自动切换初识

【前提&#xff1a;这里以一般的单片机产品为例&#xff0c;使用3.3V的供电系统&#xff0c;常见的USB供电、外接电源设配器供电和电池供电】 一、经典二极管切换电路 这是最简单的电源切换电路&#xff1a;二极管并联&#xff0c;理论上支持无数个电源切换&#xff0c;缺点是…

C++基础 -36- 模板之模板函数

模板函数格式 template <class T> void allexchange(T a,T b) {T c;c*a;*a*b;*bc; }模板函数可以增强函数的通用性 举例说明&#xff0c;使用一个模板函数实现了两个的函数的功能 #include "iostream"using namespace std;void myexchangeint(int* a,int* …

linux作业管理_jobs

4.2 作业管理 是指控制当前正在运行的进程的行为&#xff0c;也称为进程控制。 是shell的一个特性&#xff0c;使用户能在多个独立进程间进行切换。 例如&#xff0c;用户可以挂起一个正在运行的进程&#xff0c;稍后再恢复其运行。当用户使用vim编辑一个文本文件&#xff0c…

java TrueLicense实现 实现License授权许可和验证

文章目录 简述License 生成License 客户端部署 简述 可用于项目交付项目部署到甲方以及包括代码防止泄露&#xff0c;经常会出现公司内部代码被已离职人员在下家公司使用&#xff0c;底层代码的封装增加license部分&#xff0c;杜绝这块的问题。定期更换license文件可进行续期…

python scipy.spatial.distance.pdist学习详记——(待完善)

1.Python scipy.spatial.distance.pdist用法及代码示例

分享81个节日PPT,总有一款适合您

分享81个节日PPT&#xff0c;总有一款适合您 81个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1V0feg5pZ8C1Szycy40CrUw?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

二分类问题中评估模型的示例及释义:召准率、召回率等

1、评估参数定义 1.1、召准率&#xff08;Precision&#xff09; 召准率是衡量模型预测正类标签时的准确度的指标。它计算的是模型预测的正类中真正为正类的比例。换句话说&#xff0c;召准率表示在所有预测为正类的实例中&#xff0c;正确识别为正类的实例所占的比例。 其中…

SQLserver通过字符串中间截取然后分组

当我们存的数据是json的时候可以全部取出在模糊查询但是有多个重复数据的时候就没办法准确的模糊出来这个时候我们就需要用的字符串截取 --创建函数create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…

Spring MVC学习随笔-文件下载和上传(配置文件上传解析器multipartResolver)

学习视频&#xff1a;孙哥说SpringMVC&#xff1a;结合Thymeleaf&#xff0c;重塑你的MVC世界&#xff01;&#xff5c;前所未有的Web开发探索之旅 学习视频&#xff1a;【编程不良人】继spring之后快速入门springmvc,面对SpringMVC不用慌 六、SpringMVC 文件上传下载 6.1 文件…

【最通用版FPGA 实现 SPI 驱动】

最近研究了一下SPI协议的FPGA实现&#xff0c;发现网上很多大佬分享的方法都是针对某一特定的flash芯片或者某一传感器芯片来设计电路结构的。所以想根据SPI&#xff08;Serial Peripheral Interface&#xff09;的基本通讯协议实现一个通用版的SPI Master驱动。SPI在嵌入式领域…