很多时候,我们是基于python进行模型的设计和运行,可是基于python本身的速度问题,使得原生态python代码无法满足生产需求,不过我们可以借助其他编程语言来缓解python开发的性能瓶颈。这里简单介绍个例子,以此完成如何先基于cuda编写瓶颈函数,然后在将接口通过cpp进行封装,最后以库的形式被python调用。

1 cpp+python

首先,介绍下如何python调用cpp的代码。这里极力推荐pybind11。因为pybind11是一个轻量级,只包含头文件的库,他可以在C++中调用python,或者python中调用C++代码。其语法类似Boost.Python。可是不同的是Boost是一个重量级的库,因为为了兼容几乎所有的C++编译器,所以需要支持哪些最老的,bug最多的编译器。该作者考虑到现在c11都很普及了,所以丢弃那些之前的东西,从而打造这么一个轻量级的库。我们通过代码统计:

首先是对pybind11的安装:

git clone https://github.com/pybind/pybind11.git
cd pybind11
mkdir build && cd build
cmake ../
make -j32

上述cmake需要3.2及以上版本。最后输出结果如下图所示:



这里简单呈现下一级目录:

为了实现python调用cpp,我们先建立个文件名叫test.cpp

#include<pybind11/pybind11.h>

namespace py = pybind11;

int
add(int i, int j){
return i+j;
} // 该宏会在python的import语句触发
PYBIND11_MODULE(example, m){
m.doc() = "pybind11 example plugin";
m.def("add", &add, "a function which adds two numbers",
py::arg("i"), py::arg("j"));
}

然后执行:

g++  -Wall -shared -std=c++11 -fPIC \
-I/home/zzc/software/pybind11/include \
`cd /home/zzc/software/pybind11 && python3 -m pybind11 --includes` \
test.cpp \
-o example`python3-config --extension-suffix`

结果如下图



接下来,我们将其改成参数支持numpy,可参考官网文档pybind11—python numpy与C++数据传递

#include<pybind11/pybind11.h>
#include<pybind11/numpy.h> namespace py = pybind11; int
add(py::array_t<float> &array, int col){ py::buffer_info buf1 = array.request();
float *p = (float *)buf1.ptr;
for (int i=0; i<col; i++){
printf("cur value %lf\n", *p++);
}
return 0;
} PYBIND11_MODULE(example, m){
m.doc() = "pybind11 example plugin";
m.def("add", &add, "a function which adds two numbers");
}

然后依然用上述命令编译成so,调用结果如下图:

更详细的pybind11使用方法,可阅读官方文档

2 cuda+cpp+python

这里只介绍如何编写cuda的代码,然后提供python接口。通过调查pybind11的issues:alias template error with Intel 2016.0.3 compilers,如果直接编写cu代码,然后一步到位,会触发很多问题。而如这里最后所述,较好的方式就是分开:

  • 编写cuda代码,并生成动态链接库;
  • 编写cpp代码,通过函数引用方式用pybind11进行接口封装;
  • python导入对应模块即可使用。



如上图所示,首先,编写cuda代码,这里为了简洁,我们只写一个printf

// cuda_test.cu
#include<cuda_runtime.h>
#include<stdio.h> __global__ void
kernel(){
printf("inside in kernel\n");
} int
cuda(int a, int b){ kernel<<<1,10>>>();
cudaDeviceSynchronize(); return 0;
}

对应头文件:

//cuda_test.h
int cuda(int, int);

然后我们将其用nvcc编译成动态链接库

nvcc --shared -Xcompiler -fPIC cuda_test.cu -o libcutest.so



结果如上图

接着,我们借助pybind11,此时增加了几行

#include<pybind11/pybind11.h>
#include"cuda_test.h" //新增的 namespace py = pybind11; int
add(int i, int j){
return i+j;
} PYBIND11_MODULE(example, m){
m.doc() = "pybind11 example plugin";
m.def("add", &add, "a function which adds two numbers",
py::arg("i"), py::arg("j"));
m.def("cuda", &cuda,"testing",
py::arg("a"), py::arg("b")); //新增的
}

然后输入如下编译方式:

g++  -Wall -shared -std=c++11 -fPIC \
-L. -lcutest \
-I/home/zzc/software/pybind11/include \
`cd /home/zzc/software/pybind11 && python3 -mpybind11 --includes` \
test.cpp \
-o example`python3-config --extension-suffix`

此时生成结果



然后使用

混合编程[python+cpp+cuda]的更多相关文章

  1. 混合编程:如何用python11调用C++

    摘要:在实际开发过程中,免不了涉及到混合编程,比如,对于python这种脚本语言,性能还是有限的,在一些对性能要求高的情景下面,还是需要使用c/c++来完成. 那怎样做呢?我们能使用pybind11作 ...

  2. C# 托管和非托管混合编程

    在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难.   最直接的实现托管与非托管编程的方法就是 ...

  3. mpi和cuda混合编程的正确编译

    针对大数据的计算,很多程序通过搭建mpi集群进行加速,并取得了很好的效果.算法内部的加速,当前的并行化趋势是利用GPU显卡进行算法加速.针对并行性非常好的算法,GPU加速效果将远大于集群带来的加速效果 ...

  4. Python和C++的混合编程(使用Boost编写Python的扩展包)

    想要享受更轻松愉悦的编程,脚本语言是首选.想要更敏捷高效,c++则高山仰止.所以我一直试图在各种通用或者专用的脚本语言中将c++的优势融入其中.原来贡献过一篇<c++和js的混合编程>也是 ...

  5. 批处理与python代码混合编程的实现方法

    批处理可以很方便地和其它各种语言混合编程,除了好玩,还有相当的实用价值, 比如windows版的ruby gem包管理器就是运用了批处理和ruby的混合编写, bathome出品的命令工具包管理器bc ...

  6. 使用 ctypes 进行 Python 和 C 的混合编程

    Python 和 C 的混合编程工具有很多,这里介绍 Python 标准库自带的 ctypes 模块的使用方法. 初识 Python 的 ctypes 要使用 C 函数,需要先将 C 编译成动态链接库 ...

  7. 在Qt(C++)中与Python混合编程

    一.PythonQt库 在Qt(C++)中与Python混合编程,可以使用PythonQt库. 网站首页:http://pythonqt.sourceforge.net 下载页面:https://so ...

  8. CUDA+OpenGL混合编程

    CUDA+OpenGL混合编程示例: #include <stdio.h> #include <stdlib.h> #include "GL\glew.h" ...

  9. 混合编译.c/.cpp与.cu文件

    混合编译.c/.cpp与.cu文件 项目中用到cuda编程,写了kernel函数,需要nvcc编译器来编译..c/.cpp的文件,假定用gcc编译. 如何混合编译它们,整体思路是:.cu文件编译出的东 ...

随机推荐

  1. 互联网寒冬,阿里Ant Design还开坑,程序员该何去何从?

    金山都成立三十年了,不得不感叹中国在这三十年中,互联网确实是一步一步的在改变人们生活的方方面面,随着国家的发展,一大批企业搭上了互联网这趟高速列车走过了这几十年的风风雨雨,当然也造就了一批批传统行业无 ...

  2. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(2)- KBOOT形态(ROM/Bootloader/Flashloader)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT形态. 痞子衡在前一篇文章里简介了 KBOOT架构,我们知道KBOOT是一个完善的Bootl ...

  3. 痞子衡嵌入式:串口调试工具Jays-PyCOM诞生记(3)- 串口功能实现(pySerial)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是串口调试工具Jays-PyCOM诞生之串口功能实现. 串口调试助手是最核心的当然是串口数据收发与显示的功能,Jays-PyCOM借助的是 ...

  4. Java8之Optional类

    写在前头 今天再看阿里的Java开发手册,里面异常处理第10条提到这样一个建议. [推荐]防止 NPE ,是程序员的基本修养,注意 NPE 产生的场景:1 ) 返回类型为基本数据类型,return 包 ...

  5. MTF测试图卡规格

    1.Imatest Chart Finder计算图卡大小 测试camera MTF时,需要知道所需要的图卡的大小,Imatest提供了一个网页,只要输入sensor的像素, 镜头的视场角,还有镜头到图 ...

  6. 学JAVA第九天,for循环算质数及for遍历数组的方法。

    昨天终于收到了评论,老开心了!!! 算质数之前是我最怕的一件事,以前上学不好好学,之前学C#的时候也没好好研究, 直到今天老师逼我要用JAVA算质数,硬着头皮琢磨老半天才琢磨透,现在看来也挺简单的. ...

  7. 手机端input[type=date]的placeholder不起作用

    <div class="input clearfix"> <label class="fl">起始日期</label> &l ...

  8. C++语法小技巧

    前言 写的很乱,各种内容都有.仅仅是为了记录一下 而且内容极其不严谨(没错,只有实践,没有理论)!请各位谨慎驾驶! 强制内联 #define Inline __inline__ __attribute ...

  9. HTML和CSS前端教程03-CSS选择器

    目录 1. CSS定义 2. 创建CSS的三种方法 2.1. 元素内嵌(权重最高) 2.2. 文档内嵌 2.3. 外部引用 3. CSS层叠和继承 3.1. 浏览器样式 3.2. 样式表层叠 3.3. ...

  10. Android apk安装时出现“解析软件包错误”

    有时候在安装apk的时候会出现解析软件包出错 (Android studio)解决方法如下: 关闭Instant Run功能: File-Settings-...看下图: 将红色框内的勾取消. 如果还 ...