很多时候,我们是基于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. 如何将视频导入到ipad中并播放

    首先在电脑上下载并安装itunes,然后用apple账号登入, 在ipad上从apple store中下载一个播放器如KMPlayer 点击itunes上小手机的图标,找到文件共享,选中应用KMPla ...

  2. windows7安装MySQL-python遇到的坑

    最近在windows环境上搭建flask使用环境,遇到过很多坑,这次就记录下安装flask-mysqldb所遇到的坑. 正常逻辑是使用pip install flask-mysqldb进行安装.但是会 ...

  3. Python迭代和解析(1):列表解析

    解析.迭代和生成系列文章:https://www.cnblogs.com/f-ck-need-u/p/9832640.html Python中的解析 Python支持各种解析(comprehensio ...

  4. cocos creator主程入门教程(二)—— 弹窗管理

    五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 我们已经知道怎样制作.加载.显示界面.但cocos没有提供一个弹窗管理模块,对于一个多人合作的项目,没有 ...

  5. C#对象比较的总结

    简单整型比较: 从这里可以看出整型比较无论是==和Equals方法都是进行比较,比较“正常” ; ; Console.WriteLine(m1 == m2);//值比较True Console.Wri ...

  6. Java开发笔记(二十六)方法的输出参数

    前面介绍了方法的输入参数,与输入参数相对应的则为输出参数,输出参数也被称作方法的返回值,意思是经过方法的处理最终得到的运算数值.这个返回值可能是整型数,也可能是双精度数,也可能是数组等其它类型,甚至允 ...

  7. Java 学习笔记 使用synchronized实现生产者消费者模式

    说明 Object.wait()使当前的线程进入到等待状态(进入到等待队列) Object.notifyAll() 唤醒等待中的全部线程 Object.notify() 随机唤醒一个线程 代码 con ...

  8. 如何使用纯CSS制作特效导航条?

    先上张图,如何使用纯 CSS 制作如下效果? 在继续阅读下文之前,你可以先缓一缓.尝试思考一下上面的效果或者动手尝试一下,不借助 JS ,能否巧妙的实现上述效果. OK,继续.这个效果是我在业务开发的 ...

  9. maven 聚合

    聚合很简单, 在父 pom 中写出子 pom 文件的路径即可 <name>parent Maven Webapp</name> <!-- FIXME change it ...

  10. C#判断远程计算机的指定端口是否打开的代码

    如下的内容段是关于C#判断远程计算机的指定端口是否打开的内容,应该能对小伙伴有一些用. using System.Net;if(!string.IsNullOrEmpty(txtPort.Text)) ...