jvm jni 及 pvm pybind11 大批量数据传输及优化
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=116)
环境说明
- android 手机
- linux python环境
前言
近几个月来,对我来说,发生了许许多多的事情,导致有很多idea,但是都未形成好的文章。最近,趁着这个机会,写一篇。
由于业务的安排,我们需要在c/c++层与java和python层进行数据交换,数据量有大有小,但是由于我们业务上对这个数据交换的延时有一定的要求,因此有些问题需要我们解决。在我们的实验过程中,我们发现了在常规情况下,在jvm中用新创建ByteArray/FloatArray进行大数据量(6Mb byte/2Mb floats)的传输,时间在5ms/7ms,在pvm中用新创建bytearray大数据量(8Mb byte)的传输,时间在1ms左右。从实验情况来看,我们需要优化jvm中进行大数据量传输的方法。
我以前写过关于java,python和c/cpp交互的一些文章,感兴趣可以参考。
- 《C++ 调用 Python 总结(一)》 https://blog.csdn.net/u011728480/article/details/103903612
- 《java 手动生成jni头文件(JNI静态注册)》 https://blog.csdn.net/u011728480/article/details/87260113
- 《Android JNI静态和动态注册 、Java Reflect(C或C++层反射和JAVA层反射)、Java 可变参数(JNI实现)》 https://blog.csdn.net/u011728480/article/details/78963494
jvm jni篇
jni常规大量数据交换方法网上有许多,基本都是如下所示:
在java往c/cpp返回时,一般都是获取数据的底层地址,然后针对地址操作即可。
jbyteArray array;//or jfloatArray array; passed by jni-func
void * _you_wanted_ptr = env->GetPrimitiveArrayCritical(array, nullptr);
// TODO
env->ReleasePrimitiveArrayCritical(array, _you_wanted_ptr, JNI_ABORT);
在c/cpp往java传输大量数据时,有两种方式,一种是直接new一个数组,然后返回的方式,一种就是获取java层的数组地址,然后直接修改相关的数据即可。其基本如下所示:
// slow way
int len = xxx;
void * data_ptr = xxx;
jXXXArray array = env->NewXXXArray(len);
env->SetXXXArrayRegion(array, 0, len, (const jXXX *) data_ptr);
return array;
// fast way
jbyteArray array;//or jfloatArray array; passed by jni-func
int len = xxx;
void * data_ptr = xxx;
env->SetXXXArrayRegion(array, 0, len, (const jXXX *) data_ptr);
这里在使用fast way模式后,在jvm中用进行大数据量(6Mb byte/2Mb floats)的传输,时间在0.88ms/1ms,注意,有使用限制。这里一定要注意多线程安全的问题。
pvm pybind11篇
在pybind11中,大规模数据传输一般有两种数据结构,一种是py::bytes,一种就是我们常见的numpy数组,特别是在图像处理中,numpy数组是最常见的一种格式。下面,根据这两种方式,分别介绍。
py::bytes 类型传输
python 层传给c/cpp。
const py::bytes &value;//passed by pybind11-func
Py_ssize_t size = PyBytes_GET_SIZE(value.ptr());
char * ptr = PyBytes_AsString(value.ptr());
//TODO
c/cpp 层传给python。
char * buf = xxx;
int len = xxx;
return py::bytes(buf, len);//In pybind11, return to pvm
注意,在py::bytes中,也有直接修改地址的方式,这里就不提供了(python buffer protocol),有心人自己去研究吧。
numpy数据传输
这个也有像py::bytes那样创建数组,然后返回的方式,这里就不提供了。这里主要还是演示一下怎么快速在c/cpp中获取numpy数据。其实这里的数据传输也就是直接获取numpy数组地址,基本大差不差。
c/cpp到python
// python buffer protocol
py::array_t<float, py::array::c_style | py::array::forcecast> &buffer;//passed by pybind11-func
auto buf_info = buffer.unchecked<1>();
char * ptr = (char *)buf_info.data(0)
// set value to ptr(numpy)
// get value from ptr(numpy)
注意,这里使用到一个叫做python buffer protocol的东西,有兴趣大家可以看看,我在这个上并没有深究。
pybind11中内存管理问题
在pybind11中,要小心管理内存,特别是注意以下两种调用的区别。
根据https://pybind11.readthedocs.io/en/stable/advanced/classes.html#non-public-destructors的说明,我们一般会有两种情况需要选择使用。
// 单例
class MyClass{
private:
~MyClass(){}
};
// 禁止unique_ptr 调用 析构函数, 所有资源释放需要在cpp侧进行完成。
py::class_<MyClass, std::unique_ptr<MyClass, py::nodelete>>(m, "MyClass")
.def(py::init<>())
// 一般class
class MyClass{
public:
~MyClass(){}
};
// unique_ptr 析构时自动调用析构函数,所有资源释放由unique_ptr完成。
py::class_<MyClass, std::unique_ptr<MyClass>>(m, "MyClass")
.def(py::init<>())
后记
总的来说,在jvm和pvm中,通过操作固定数组的底层指针,我们可以快速的获取数据和传输数据。但是存在一些现象,例如需要注意一些原子操作和pvm/jvm中数组的生命周期的问题,我这里建议,如果是大规模数据传输,建议直接全局数组,这样保证生命周期问题。
参考文献
[1]https://pybind11.readthedocs.io/en/stable/advanced/classes.html#non-public-destructors
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
jvm jni 及 pvm pybind11 大批量数据传输及优化的更多相关文章
- [转帖]Java虚拟机(JVM)体系结构概述及各种性能参数优化总结
Java虚拟机(JVM)体系结构概述及各种性能参数优化总结 2014年09月11日 23:05:27 zhongwen7710 阅读数 1437 标签: JVM调优jvm 更多 个人分类: Java知 ...
- NDK(20)JNI的5大性能缺陷及优化技巧
转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...
- NDK(21)JNI的5大正确性缺陷及优化技巧(注意是正确性缺陷)
转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...
- JVM调优(这里主要是针对优化基于分布式Mahout的推荐引擎)
优化推荐系统的JVM关键参数 -Xmx 设定Java允许使用的最大堆空间.例如-Xmx512m表示堆空间上限为512MB -server 现代JVM有两个重要标志:-client和-server,分别 ...
- Java虚拟机(JVM)体系结构概述及各种性能参数优化总结
转自:http://blog.csdn.net/zhongwen7710/article/details/39213377 第一部分:相关的概念 数据类型 Java虚拟机中,数据类型可以分为两类:基本 ...
- Android数据库大批量数据插入优化
对比在android中批量插入数据的3中方式对比(各插入1W条数据所花费的时间): 1. 一个一个插入 public static boolean insert(SQLiteOpenHelper op ...
- JVM之java并发 ——线程安全与锁优化
概述 人们很难想象现实中的对象在一项工作进行期间,会被不停地中断和切换,对象的属性(数据)可能会在中断期间被修改和变“脏”,而这些事情在计算机世界中则是很正常的事情.有时候,良好的设计原则不得不向现实 ...
- 深入了解JVM虚拟机8:Java的编译期优化与运行期优化
java编译期优化 java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程:1.前端编译:把.java文件转变为.class文件2.后端编译:把字节码转变为机器码3.静态提前编译: ...
- Java:导出Excel大批量数据的优化过程
背景 团队目前在做一个用户数据看板(下面简称看板),基本覆盖用户的所有行为数据,并生成分析报表,用户行为由多个数据来源组成(餐饮.生活日用.充值消费.交通出行.通讯物流.交通出行.医疗保健.住房物业. ...
随机推荐
- 小米手机简单 ROOT教程(百分百成功)
大家都知道啊,由于小米自带的换机软件不支持一些应用数据的还原,所以需要使用钛备份来还原应用和数据.但是钛备份需要root才能用,因为有些机器刚出没多久,第三方的recovery也没有,所以需要找到一种 ...
- VSCode 前端常用插件集合
Visual Studio Code 是由微软开发的一款免费.跨平台的文本编辑器.由于其卓越的性能和丰富的功能,它很快就受到了大家的喜爱. 但工欲善其事必先利其器,以下是本人为前端开发收集的常用的vs ...
- 5. VIM编辑器
Vim编辑器中设置了3种模式-命令模式.末行模式和编辑模式 命令模式:控制光标移动,可对文本进行复制.粘贴.删除和查找等工作. 输入模式:正常的文本录入. 末行模式:保存或退出文档,以及设置编辑环境. ...
- js实现图片懒加载原理
原理 图片懒加载是前端页面优化的一种方式,在页面中有很多图片的时候,图片加载就需要很多时间,很耗费服务器性能,不仅影响渲染速度还会浪费带宽,为了解决这个问题,提高用户体验,所以就出现了懒加载这种方式来 ...
- InnoDB的逻辑存储结构是什么,表空间组成包括哪些?
一.表空间 在InnoDB中我们创建的表还有对应的索引数据都存储在扩展名为.ibd 的文件中,这个文件路径可以先通过查mysql变量datadir来得到,然后进入对应的数据库名目录,会看到很多ibd, ...
- 基本命令学习 -(4)链接文件:ln命令
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 前言 在Windows系统中,快捷方式是指向原始文件的一个链接文件,原文件一旦被删除或剪切到其 ...
- 微信小程序云开发如何实现微信支付,业务逻辑又怎样才算可靠
今天打了几把永劫无间后,咱们来聊一聊用云开发来开发微信小程序时,如何实现微信支付,并且保证业务逻辑可靠. @ 目录 注册微信支付商户号 小程序关联商户号 业务逻辑 代码实现 注册微信支付商户号 点击& ...
- FTP主动模式上传文件时返回"ftp: accept: Resource temporarily unavailable"
FTP主动模式上传文件时返回 Passive mode off ftp: accept: Resource temporarily unavailable 这个问题要从ftp的2种模式说起 PORT ...
- VMware虚拟机中安装Linux操作系统(ubuntu)
一.准备工作: 1.下载VMware虚拟机 下载地址:https://www.vmware.com/cn/products/workstation-pro/workstation-pro-evalua ...
- drools的类型声明(Type declarations)
一.背景 在我们编写drl规则的时候,有些时候需要自己声明一些类,用于辅助之后的规则运行,如果需要用到的类还需要在java中预先声明出来,这样就不灵活了,那么是否可以在drl文件中声明一个类呢?可以使 ...