当前位置: 首页 > news >正文

一个完整的手工构建的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 源代码的最顶层;

相关文章:

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

1&#xff0c; 源代码 仅仅是加入了模板函数和对应的 .cuh文件&#xff0c;当前的目录结构如下&#xff1a; icmm/gpu/add.cu #include <stdio.h> #include <cuda_runtime.h>#include "inc/add.cuh"// different name in this level for different type…...

rdf-file:SM2加解密

一&#xff1a;SM2简介 SM2是中国密码学算法标准中的一种非对称加密算法&#xff08;包括公钥和私钥&#xff09;。SM2主要用于数字签名、密钥交换和加密解密等密码学。 生成秘钥&#xff1a;用于生成一对公钥和私钥。公钥&#xff1a;用于加密数据和验证数字签名。私钥&…...

harmonyOS学习笔记之@Styles装饰器与@Extend装饰器

Styles装饰器 定义组件重用样式 自定义样式函数使用装饰器 可以定义在组件内或全局,内部优先级>外部,内部不需要function,外部需要function 定义在组件内的styles可以通过this访问组件内部的常量和状态变量,可以在styles里通过事件来改变状态变量 弊端:只支持通用属性和通用…...

GateWay的路由与全局过滤器

1.断言工厂 我们在配置文件中写的断言规则只是字符串&#xff0c;这些字符串会被Predicate Factory读取并处理&#xff0c;转变为路由判断的条件 例如Path/user/**是按照路径匹配&#xff0c;这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePr…...

MuleSoft 中的细粒度与粗粒度 API

API 设计是一个令人着迷的话题。API 设计的一个重要方面是根据 API 的特性和功能确定正确的“大小”。所有建筑师都必须在某个时候解决过这个问题。在本文中&#xff0c;我将尝试对我们在获得“正确的”粒度 API 之前需要考虑的各种参数进行一些深入的探讨&#xff1a; 可维护…...

【笔记】2023最新Python安装教程(Windows 11)

&#x1f388;欢迎加群交流&#xff08;备注&#xff1a;csdn&#xff09;&#x1f388; ✨✨✨https://ling71.cn/hmf.jpg✨✨✨ &#x1f913;前言 作为一名经验丰富的CV工程师&#xff0c;今天我将带大家在全新的Windows 11系统上安装Python。无论你是编程新手还是老手&…...

Android Wifi断开问题分析和802.11原因码

Android Wifi连接和断链分析思路。 1.密码错误导致的连接失败 2.关联被拒绝 3.热点未回复AUTH_RSP或者STA未收到 AUTH_RSP 4.热点未回复ASSOC_RSP或者STA未收到ASSOC_RSP 5.DHCP FAILURE 6.发生roaming 7.AP发送了DEAUTH帧导致断开连接 8.被AP踢出&#xff0c;这个原因…...

【Cell Signaling + 神经递质(neurotransmitter) ; 神经肽 】

Neuroscience EndocytosisExcitatory synapse pathwayGlutamatergic synapseInflammatory PainInhibitors of axonal regenerationNeurotrophin signaling pathwaySecreted Extracellular VesiclesSynaptic vesicle cycle...

当springsecurity出现SerializationException问题

当springsecurity出现SerializationException问题 01 异常发生场景 当我使用springsecurity时&#xff0c;登录成功后携带token访问接口出了问题 org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized field "userna…...

[SaaS] 广告创意中stable-diffusion的应用

深度对谈&#xff1a;广告创意领域中 AIGC 的应用这个领域非常快速发展&#xff0c;所以你应该保持好奇心&#xff0c;不断尝试新事物&#xff0c;不断挑战自己。https://mp.weixin.qq.com/s/ux9iEABNois3y4wwyaDzAQ我对AIGC领域应用调研&#xff0c;除了MaaS服务之外&#xff…...

第八节HarmonyOS @Component自定义组件的生命周期

在开始之前&#xff0c;我们先明确自定义组件和页面的关系&#xff1a; 1、自定义组件&#xff1a;Component装饰的UI单元&#xff0c;可以组合多个系统组件实现UI的复用。 2、页面&#xff1a;即应用的UI页面。可以由一个或者多个自定义组件组成&#xff0c;Entry装饰的自定…...

【Openstack Train安装】五、Memcached/Etcd安装

本文介绍Memcached/Etcd安装步骤&#xff0c;Memcached/Etcd仅需在控制节点安装。 在按照本教程安装之前&#xff0c;请确保完成以下配置&#xff1a; 【Openstack Train安装】一、虚拟机创建 【Openstack Train安装】二、NTP安装 【Openstack Train安装】三、openstack安装…...

29 kafka动态配置

为什么需要动态配置 线上运行的kafka broker修改配置需要重启的话&#xff0c;影响比较大。需要一个不需要重启就能使参数生效的功能 使用的场景 配置优先级&#xff1a; per-broker参数 > cluster-wide参数 > static参数 > 默认参数 1.动态调整network线程数和工…...

JIRA部分数据库结构

表jiraissue&#xff08;问题表&#xff09; 字段 数据类型 是否为空 KEY 说明 ID decimal(18,0) NO PRI 主键 pkey varchar(255) YES MUL 查看主键&#xff0c;“项目ID” PROJECT decimal(18,0) YES MUL 项目外键&#xff0c;项目表外键 REPORTER varch…...

RK3568平台开发系列讲解(Linux系统篇) dtb 到 device_node 的转化

🚀返回专栏总目录 文章目录 一、dtb 展开流程二、dtb 解析过程源码分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍通过设备树 dtb 如何展开成 device_node 一、dtb 展开流程 设备树源文件编写: 根据设备树的基本语法和相关知识编写符合规范的设备树。…...

屏幕的刷新率和分辨率

一、显示器刷新率和分辨率的区别 1、显示器刷新率是什么意思? 刷新率是指电子束对屏幕上的图像重复扫描的次数。刷新率越高,所显示的图像(画面)稳定就越好。 刷新率高低直接决定其价格&#xff0c;但是由于刷新率与分辨率两者相互制约&#xff0c;因此只有在高分辨率下达到…...

面试官:请说说JS中的防抖和节流

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 前言 为什么要做性能优化&#xff1f;性能优化到底有多重要&#xff1f; 性能优化是为了提供更好的用户体验、加…...

[足式机器人]Part4 南科大高等机器人控制课 Ch00 课程简介

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;CLEAR_LAB 课程主讲教师&#xff1a; Prof. Wei Zhang 南科大高等机器人控制课 Ch00 课程简介 1. What is this course about?2. Tentative Schedule暂定时间表 1. What is this course about? Develop a solid found…...

SSM项目实战-登录验证成功并路由到首页面,Vue3+Vite+Axios+Element-Plus技术

1、util/request.js import axios from "axios";let request axios.create({baseURL: "http://localhost:8080",timeout: 50000 });export default request 2、api/sysUser.js import request from "../util/request.js";export const login (…...

Python----网络爬虫

目录 1.Robots排除协议 2.request库的使用 3.beautifulsoup4库的使用 Python网络爬虫应用一般分为两部: &#xff08;1&#xff09;通过网络连接获取网页内容 &#xff08;2&#xff09;对获得的网页内容进行处理 - 这两个步骤分别使用不同的函数库&#xff1a;requests …...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...