python调用c++动态库_使用python 调用 pybind11封装的 cuda C++ 动态链接库

2023-11-10

使用python 调用 pybind11封装的 cuda C++ 动态链接库

pybind11是可以使C++和python程序间互相调用的轻量头文件库,它可以将C++代码编译成python可调用的动态链接库,

pybind11可以自动实现C++中vector、list等与python中list的自动转换,也可以C++中多维数组自动转换为 numpy.ndarray的格式。

pybind11中numpy.ndarray在C++中的表现形式:

py::array_t np_multiply_Cublas(py::array_t &inLeft, py::array_t &inRight)

{

//可通过此函数传入python中的numpy.ndarray数据,在C++中表现为py::array_t格式。

py::buffer_info bufLeft = inLeft.request(), bufRight = inRight.request();

//request方法活得对py::array_t的绑定,包括维度、数据指针、size、shape等参数

assert(bufLeft.ndim == bufRight.ndim);

assert(bufLeft.ndim == 2);

assert(bufLeft.shape[1] == bufRight.shape[0]);

const int M = bufLeft.shape[0], K = bufLeft.shape[1], N = bufRight.shape[1];

// 实现矩阵乘法,C=A*B

//M、K、N分别是A的行数、列数、B的列数,C的shape为{M,N}

auto result = py::array_t(M * N);

result.resize({M, N});

py::buffer_info bufResult = result.request();

float *ptrLeft = (float *)bufLeft.ptr,

*ptrRight = (float *)bufRight.ptr,

*ptrResult = (float *)bufResult.ptr; //获得数据指针

Gpu_mul(ptrLeft, ptrRight, ptrResult, M, K, N);//将响应参数传输cuda C++编写的矩阵乘法函数中结果保存在ptrResult中

return result;

//返回result,result也是py::array_t格式,也就是python中 的numpy.ndarray

}

以下是简单的python调用接口封装

PYBIND11_MODULE(mylib, m)

{

// m.doc("use cuda and demo");

//mylib代表封装的python模块名

m.def("np_sum", &np_sum, "Add two Numpy arrays use cuda");

m.def("Gpu_mul", &np_multiply, "Multuply tow arrays use cuda flag==1 use shared memory,flag==2 use global memory");

m.def("Gpu_Cublas", &np_multiply_Cublas, "Multuply tow arrays use cublas");

//"Gpu_Cublas"代表python中对应的函数,&np_multiply_Cublas是对应的C++函数指针,之后的字符串是python中的函数doc

}

以下是python中的调用示例

import os

os.sys.path.append("../build/bin")

os.sys.path.append("build/bin")

os.sys.path.append("build/bin/Release")#这三个路径是 mylib.cp37-win_amd64.pyd 动态库可能存在的路径

import mylib as my # 载入mylib模块

import time

import numpy as np

Ga = np.random.rand(50* 100, 31 * 100).astype(np.float32)

Gb = np.random.rand(31 * 100, 50 * 100).astype(np.float32)

# 生成随机numpy.ndarray,为float32格式

Gstart = time.time()

Ghc = Ga @ Gb # 调用numpy自带的矩阵乘法函数

Gpaush = time.time()

Gc = my.Gpu_Cublas(Ga, Gb) # 调研C++端的liys cublas矩阵乘法函数

Gend = time.time()

print("the numpy cost", (Gpaush - Gstart)) # 比较两者耗时

print("the cublas cost time ", (Gend - Gpaush))

print("the two result are same?", (Ghc == Gc).any()) # 比较两个答案是否相等

以下是C++中利用cublas实现矩阵乘法的代码实现

void useCublas(float *_A, float *_B, float *_C, int M, int K, int N)

{

cublasHandle_t handle;

cublasCreate(&handle);

float alpha = 1, beta = 0;

cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, N, M, K, &alpha, _B, N, _A, K, &beta, _C, N);//C=alpha*A*B+beta,

//cublas中矩阵是列优先的格式,而C++是行优先的格式,所以调用的时候是_B在前,_A在后 C^T = B^T*A^T

}

void Gpu_mul(float *ptrLeft, float *ptrRight, float *ptrResult, int M, int K, int N,int flage)

{

float *d_a, *d_b, *d_c;

cudaMalloc((void **)&d_a, M * K * sizeof(float));

cudaMalloc((void **)&d_b, K * N * sizeof(float));

cudaMalloc((void **)&d_c, M * N * sizeof(float));

CHECK(cudaMemcpy(d_a, ptrLeft, M * K * sizeof(float), cudaMemcpyHostToDevice));

CHECK(cudaMemcpy(d_b, ptrRight, K * N * sizeof(float), cudaMemcpyHostToDevice));

constexpr const int TP = 16;

dim3 threadsPer(TP, TP);

dim3 blocksPer((M + TP - 1) / TP, (N + TP - 1) / TP);

if (flage == 1)

{

matrix_MulG<<>>(d_a, d_b, d_c, M, K, N);

}

else if (flage == 0)

{

useCublas(d_a, d_b, d_c, M, K, N); //如果flag==0,调用cublas的矩阵乘法,否则调用 手写的cuda核函数进行矩阵相乘。

}

else if (flage == 2)

{

matrix_glbal_mul<<>>(d_a, d_b, d_c, M, K, N);

}

CHECK(cudaMemcpy(ptrResult, d_c, M * N * sizeof(float), cudaMemcpyDeviceToHost));

CHECK(cudaFree(d_a));

CHECK(cudaFree(d_b));

CHECK(cudaFree(d_c));

}

矩阵乘法cuda核函数版,最直接的版本,直接使用全局内存

__global__ void matrix_glbal_mul(float*_A ,float* _B,float* _C, int M,int K,int N)

{

int x = threadIdx.x + blockIdx.x * blockDim.x; //对应于_C的列

int y = threadIdx.y + blockIdx.y * blockDim.y; //对应于_C的行索引

if(y>=M || x>=N)

return;//防止越界

float sum = 0.;

for (int i = 0;i

{

sum += _A[y * K + i] * _B[i * K + x];//A[y][i]*B[i][x]的乘累加

}

_C[y * N + x] = sum;

}

//这个版本,A和B中的每个元素都需要读取多次,由于GPU中global memory读写速度远小于每个block的shared memory

利用shared memory的储存A和B的数据,global memory中的每个数据只需读取一次

template

__global__ void matrix_MulG(float *_A, float *_B, float *_C, int M, int K, int N)

{

__shared__ float subM[TILE_WIDTH][TILE_WIDTH];

__shared__ float subN[TILE_WIDTH][TILE_WIDTH];//每个block中的所有threads共享同一的shared memory

int x = threadIdx.x + blockIdx.x * blockDim.x; //

int y = threadIdx.y + blockIdx.y * blockDim.y; //y为行,x为列 对应与结果C的行和列

int tx = threadIdx.x;

int ty = threadIdx.y;//该thread 在所属block中的索引

float tmp = 0.;

for (int i = 0; i < ((K + TILE_WIDTH - 1) / TILE_WIDTH); ++i)

{

if ((tx + i * TILE_WIDTH) < K && (y < M))

subM[ty][tx] = _A[y * K + tx + i * TILE_WIDTH]; //共享内存参数更新

else

{

subM[ty][tx] = 0.;

}

if ((ty + i * TILE_WIDTH) < K && (x < N))

subN[ty][tx] = _B[(ty + i * TILE_WIDTH) * N + x];

else

{

subN[ty][tx] = 0.;

}

__syncthreads();// block内thread同步

for (int j = 0; j < TILE_WIDTH; ++j)

{

tmp += subM[ty][j] * subN[j][tx];

}

__syncthreads();

}

if (y < M && x < N) //越界检查

_C[y * N + x] = tmp;

}

最终调用的python测试,运行结果可能在不同机器上不同

the numpy cost 4.054656028747559

the cublas cost time 2.555680513381958

the two result are same? True

the Gpu with shared memory cost time 4.681894779205322

the two result are same? True

the Gpu with global memory cost time 4.836901903152466

the two result are same? True

实际上如果需要在Python代码中调用cuda核函数,可以用numba加速库的numba.cuda模块。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python调用c++动态库_使用python 调用 pybind11封装的 cuda C++ 动态链接库 的相关文章

  • Python_单下划线和双下划线

    属性 x 公有变量 x 私有变量 在py中不能完全做到私有 只能说 伪私有 只是一种良好的书写习惯 不希望被其他类或者子类访问 x 后置下划线 避免与py中的关键字冲突 方法 fun 私有方法 无法在外部直接访问 只能允许本身访问 子类也不
  • 目的:ubuntu配置使用opengl - 初探-创建一个空窗口

    目的 ubuntu配置使用openGL 初探 创建一个空窗口 环境 系统 Ubuntu18 04 环境 g 步骤 Ubuntu下使用openGL 搭建配置环境并测试窗口 1 openGL库 需要单独安装 由于本机是vmware虚拟机Ubun
  • 关于CittyEngine处于加载界面死机的解决方法

    1 CityEngine License无法打开 与已安装的ArcGISAdministrator冲突 在安装后破解是打开CityEngine License警告 试图执行不支持的操作 提示 CityEngine可以独立安装 并不一定要安装
  • 使用vector对数据进行排序(动态排序)

    排序思路 头函数 algorithm 中有一个函数是 upper bound start end value 它可以返回区间 start end 中第一个大于等于 value 的值的位置 再加上 vector 中自带的插入函数 insert
  • 电脑安装了lattice diamond后,再安装lattice radiant,若出现lattice radiant license checkout failed如何解决?

    我电脑安装了lattice diamond 再安装lattice radiant 设置完环境变量后 发现lattice radiant仍然会报错 如下图 检查环境变量和license都并没有什么错误 但是就是一直会出现以下情况 后面如何解决
  • UML 类图

    1 概述 目录 1 概述 1 1 UML概念 1 2 类图的概念 2 类的表示方式 2 1 普通类 2 2 抽象类 2 3 接口 3 类与类关系的表示 3 1 关联关系 Association 3 1 1 单向关联 3 1 2 双向关联 3
  • 【小程序】如何实现从底部弹出对话框

    前面两篇两篇文章介绍了如何在小程序中实现上下滑动效果以及如何用 Canvas 绘制一张图片 这一篇作为前两篇的延续 介绍如何从底部弹出一个对话框 相比而言 底部弹出对话框的功能比较通用 因此非常适合定义成组件 component 先来看一下
  • 【学习记录贴】Vue+Element-UI富文本编辑框及插入图片

    本贴会涉及以下几个技术点 Vue Element UI实现富文本编辑框 以及文本编辑框中事件拦截 插入图片 Element UI限制上传图片后 隐藏上传按钮 官网上是没有这个方法的 可以通过上传到指定张数后隐藏上传按钮来实现 form表单验
  • MyBatis-Plus删除操作知识点总结

    系列文章目录 Mybatis Plus知识点 MyBatis MyBatis Plus的基础运用 心态还需努力呀的博客 CSDN博客 Mybatis Plus SpringBoot结合运用 心态还需努力呀的博客 CSDN博客MyBaits
  • VScode自由切换输出结果窗口,输出到“终端”和“调试控制台”

    Author xiaozhu sai 软件 Visual Studio Code 点击右边的齿轮按钮 打开launch json文件 注意 console 属性即可 具体见一下代码 使用 IntelliSense 了解相关属性 悬停以查看现
  • C++ sort函数自定义排序规则

    在使用vector容器时经常要进行排序 使用排序函数sort非常方便 但是之前都是简单调用sort v begin v end 没有自定义排序规则使用sort函数的额第三个参数 下面对sort总一个简单总结 头文件 include
  • 计算机网络第2章(物理层)

    B站视频 计算机网络微课堂 有字幕无背景音乐版 网址 https www bilibili com video BV1c4411d7jb p 61 目录 2 1 物理层的基本概念 2 2 物理层下面的传输媒体 导引型传输媒体 非导引型传输媒
  • Vue弹窗传值

    场景 点击新增后 需要将这个页面的分类Id传到弹窗页面 新增的时候绑定这个分类 步骤 1 列表页面中弹窗标签中绑定 classifyId this classify
  • 演唱会为什么总是抢不到票?用Python做一个自动抢票脚本!想看谁的就看谁的!

    大麦网 是中国综合类现场娱乐票务营销平台 业务覆盖演唱会 话剧 音乐剧 体育赛事等领域 但是因为票数有限 还有黄牛们不能丢了饭碗 所以导致了 很多人都抢不到票 那么 今天带大家用Python来制作一个自动抢票的脚本小程序 文章末尾看运行效果
  • Java 基于文本界面的《员工管理系统》

    一 代码实现 1 设计分析 该管理系统使用了5个包 Package 类似于文件夹 1 bean 包含员工类 Employee 2 main 主程序的入口 3 service 主要是 业务逻辑层 的功能实现 4 util 存放工具类 此处存放
  • 【springmvc系】利用RequestBodyAdviceAdapter做接口鉴权

    需求 有个简单的需求 对于第三方接口我们需要做个简单的鉴权机制 这边使用的是非对称性加密的机制 我们提供三方公钥 他们通过公钥对接口json报文使用加密后的报文请求 我们通过对接收过来的请求某一个加密报文字段来进行RSA解密校验 考虑到日后
  • hashmap原理_HashMap原理jdk7和jdk8的区别

    一 hashMap的jdk1 7和jdk1 8区别 1 实现方式 jdk7中使用数组 链表来实现 jdk8使用的数组 链表 红黑树 2 新节点插入到链表是的插入顺序不同 jdk7插入在头部 jdk8插入在尾部jdk7中 如何在头部插入 看a
  • [Hadoop3.3.1]:Unable to load native hadoop library for your platform

    需求 linux已经启动了hadoop集群 想要在windows中用java对文件进行下载操作 错误提示 找不到winutils exe hadoop dll没有设置原因 Hadoop访问windows本地文件系统 要求Windows上的本
  • SQL Server数据库进阶

    批处理 将多条SQL语句作为一个整体去编译 生成一个执行计划 然后执行 为了将一个脚本分为多个批处理 可使用GO语句 GO语句的特点 GO语句必须自成一行 只有注释可以在同一行上 它使得自脚本的开始部分或者最近一个GO语句以后的所有语句编译

随机推荐

  • elementUI中,实现一个单元格内显示两行数据,并用其中一个数据进行排序。

    最近在公司中 有这样一个需求 表格中 一个单元格里面显示两行数据 并且可以使用其中一行进行排序 其中数据的样式也要实时变动 类似于下图 这样的话 elementUI中自带的prop就不适合了 所以 需要展示两行数据的地方 我们就用插槽来解决
  • 重叠社区发现-UEOC算法(unfold and extract overlapping communities)学习笔记

    本文提出了一种基于马尔可夫动力学模型的发现节点共享社区的算法UEOC 在UEOC方法中 为了检测出所有的自然群落 将马尔可夫随机游动方法与一种新的约束策略相结合 该策略基于相应的退火网络 21 用于展开每个群落 然后 利用一个借助电导的截止
  • 【Python编程入门】环境搭建

    作为一门跨平台的高级编程语言 Python可以运行在几乎所有主流的操作系统中 这也意味着 只要我们在本机电脑安装配置完Python环境后 便可以轻松愉快的学习Python语言了 这是一门值得大部分人学习的计算机编程语言知识 关于Python
  • angular自定义form表单元素-checkList

    实际使用form的时候 最外层的form的某个表单元素可能是个组合的 这种情况如果是可多场景复用的 最好封装一个表单元素 本文以组合复选框为例来说明下自定义表单元素的过程 实现效果 展示效果 html
  • TeamViewer三种许可证的区别是什么?

    很多想要购买TeamViewer正版许可证的用户 不清楚这三种许可证的区别 所以今天小编就为大家介绍一下 这三种许可证到底有何区别以及购买那种最划算 首先为大家介绍一下TeamViewer Business商业版许可证 如下图所示 图1 B
  • 汇编语言基础知识

    文章目录 80386常用寄存器 一 常用寄存器 1 1 通用寄存器 1 2 段寄存器 1 3 程序状态与控制寄存器 二 常用基本指令 2 1 数据传送指令 2 2 算术运算指令 2 2 1 加法指令 2 2 2 减法指令 2 2 3 乘法指
  • 查看使用systemctl启动日志

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 1 查看启动日志 journalctl f或者 journalctl xe 2 设置开机自启动 systemctl enable nginx service 3 启动ngi
  • 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java制造类企业erp23725

    面对老师五花八门的设计要求 首先自己要明确好自己的题目方向 并且与老师多多沟通 用什么编程语言 使用到什么数据库 确定好了 在开始着手毕业设计 1 选择课题的第一选择就是尽量选择指导老师擅长的课题 其实说白一点 你们的指导老师每年都是那几个
  • C3P0连接池参数配置

  • Linux系统wget unable to resolve host address解决办法

    Linux系统运行yum安装rpm包的时候提示wget unable to resolve host addresswget 无法解析主机地址 这就能看出是DNS解析的问题 错误提示 wget unable to resolve host
  • 用于CTF(MISC)的kali虚拟机更改过程记录

    Kali更改记录 安装pip2 太多工具需要python2了 安装setuptools 18 5 wget https pypi python org packages source s setuptools setuptools 18 5
  • 面向对象的编程思想和Python的继承和多态,特殊方法,引用计数

    面向对象的编程思想和Python的类 访问和属性 继承 在上一文中我们了解到了 私有的属性的访问方式 实例名 类名 私有属性名 一 私有的属性如何对外提供公有的取值和赋值方法呢 提供公有的方法作为接口进行取值 例如 class Avg Sc
  • 思科路由器NAT配置详解(转)

    思科路由器NAT配置详解 转 网络技术 2010 07 11 17 48 14 阅读104 评论0 字号 大中小 订阅
  • ubuntu安装vscode_vscode远程开发配置

    Remote development是一个支持vscode远程开发的插件 非常方便在windows下调试远程linux系统上的代码 使用配置方式如下 首先windows和远端服务器都要安装ssh windows上启用ssh服务即可 linu
  • RBAC权限管理

    RBAC权限管理 RBAC应用最为广泛的权限管理模型 核心的三要素是 用户 角色 权限 但并不仅仅局限于这三个核心要素 基于企业规模 用户规模 运维复杂度 RBCA其实是有很多的变种 从理论角度 有所谓的RBAC0 RBAC1 RBAC2
  • python opencv cv2在图片中画mask掩码/掩膜

    python opencv cv2在图片中画mask掩膜 import cv2 import numpy as np from PIL import Image import matplotlib pyplot as plt mask th
  • 年度最火的AOA蓝牙室内定位原理

    AOA 定位方法 AOA 定位方法 主要是测量信号移动台和基站之间的到达角度 以基站为起点形成的射线必经过移动台 两条射线的交点即为移动台的位置 该方法只需两个基站就可以确定 MS 的估计位置 其定位示意图如图所示
  • 语音转文字,视频转文字的新大陆!--飞书(好用记得点个赞)

    语音转文字 视频转文字的新大陆 飞书 1 选择自己对应的系统 下载飞书 飞书是字节跳动于2016年自研的新一代一站式协作平台 网址 https www feishu cn 2 下载安装之后 使用手机号 邮箱等注册登录 点击会议 点击进入子菜
  • 现代框架背后的概念

    很多初学者问 我应该学哪个框架 和 学一个框架之前需要学多少JS或TS 无数自以为是的文章都在宣传作者首选框架或库的优势 而不是向读者展示其背后的概念以做出明智的决定 那么让我们先解决第二个问题 学一个框架之前要学多少JS TS 尽可能多地
  • python调用c++动态库_使用python 调用 pybind11封装的 cuda C++ 动态链接库

    使用python 调用 pybind11封装的 cuda C 动态链接库 pybind11是可以使C 和python程序间互相调用的轻量头文件库 它可以将C 代码编译成python可调用的动态链接库 pybind11可以自动实现C 中vec