一个业务需求上需要在庞大矩阵里进行比较复杂的科学计算,进行一些通用计算时候 pandas 和 numpy 自然是首选,比如算协方差之类的,但是业务还有一些比较复杂的计算需求(比如特定环境下的开窗)不能用通用计算实现。
目前的做法是将 pd 数据导入到 python 数据结构,然后再通过 ffi 传入 rust 编写的动态链接库。虽然相比于 py 硬写性能提高了几个数量级,不过开分析看了一下这个计算当中有超过 50%的占用用在处理各种各样的类型转换上。
有一个想法是这些框架有没有提供三方接口,可以直接把指定区域的内存暴露给第三方软件使用从而省去了类型转换的麻烦(比如现在是 np.int 转 python 的 int 数据结果,再转 rust 的 usize 这个过程开销太高了,且没什么实质意义)。有无熟悉科学计算框架的老哥说一说。
(最好 py+rust 技术栈内可以解决的,cython 项目我感觉文档非常不友好,一直也没写明白过)
1
leeg810312 2022-05-18 09:22:25 +08:00 via Android
github 上的 polar 项目可以看看是否符合你的需求
|
2
LeeReamond OP @leeg810312 之前有人提过这个项目,但是用的人太少,我在论坛里还发帖问过有没有遇到什么坑的,回复寥寥,基本也是没人用的原因
|
3
qieqie 2022-05-18 09:42:10 +08:00
ndarray.tobytes()然后 reinterpret_cast
盲猜的没试过 |
4
chenxytw 2022-05-18 09:53:22 +08:00
正经途径是用 numpy c api ,可以用 C/C++ 写逻辑。
你非要用 rust 的话,看看 pyo3 和 rust-numpy |
5
leeg810312 2022-05-18 10:12:42 +08:00
@LeeReamond 最近在业余时间研究这个项目,感觉还是有点潜力,star 和活跃度都很高。Rust 本身使用就少,作为一个还在起步阶段的项目,比较适用于新技术探索或当前没有比较好的方案情况下进行技术验证,想要很成熟可靠的方案只能找商业公司普遍在用的方案了
|
6
cassidyhere 2022-05-18 10:25:34 +08:00
|
7
winglight2016 2022-05-18 11:34:03 +08:00
OS 支持跨进程访问内存吗?
|
8
julyclyde 2022-05-18 11:51:32 +08:00
@winglight2016 需要设置 shm
|
9
Huelse 2022-05-18 12:06:57 +08:00
如果是 C++的话可以考虑 pybind11
另外这个似乎和你说的很像 http://saidvandeklundert.net/learn/2021-11-06-calling-rust-from-python/ |
10
LeeReamond OP @chenxytw 虽然我不写 c++,但是因为具体实现基本只是单纯算法,感觉应该也没有大问题。问题在于工作链条感觉有些成本,因为 c++没有一个中心式的包管理系统,写码过程中还是不可避免用到各种数据结构(以及扩展的比如线程安全的 hashmap ),印象里 stl 这些是有些坑的,一般听说写 c++好像都是自己维护一个工具库。目前的 rust 方案的好处在于 crates 可以集中做包管理,我信任用量高的三方库再加上信任 rust 编译器优化,那么我可以确保写出来的码除了没用 simd 外是理论高效的。c++的话问题在于首先打通开发环境,就是从对接 numpy 到开始写第一行业务代码为止就比较困难,第二点就是似乎不太能像 rust 一样确保代码的理论高效
|
11
chenxytw 2022-05-18 13:12:16 +08:00
@LeeReamond 无意和你讨论语言优劣性。只是现状是 C++ 写 Python 扩展调用 numpy 是相对成熟的方案了,可以找到很多例子进行参考。使用 Rust 现在也有人在探索,包括我给你列举的 PyO3 和 Rust-Numpy ,但在项目中实际操练的不多,需要自己踩坑并有能力自己解决问题。
因为你是发在 Python 节点,我是认为你的主体程序是 Python ,Rust 作为扩展。这种情形下讨论最高效的,避免内存复制的使用方法是很难绕开 Python C API 和 Numpy C API 的。如果你的主体是 Rust, 那会是另一种话题了。 1. 如果是想借用 Numpy 和基于此的生态。那还是可以看看 PyO3 。PyO3 也支持从 Rust 中调用 Python 。 2. 如果只是一些确定的计算,比如就是矩阵计算,我觉得你可以找找 BLAS 的 rust 实现或者 binding 以及周边生态。 |
12
LeeReamond OP @chenxytw 可能对你来说可以很轻松地找到很多例子进行参考,但是不太熟悉 c++生态,能否帮忙指明一些适合初步接触研究的项目?
|
13
clf 2022-05-18 13:19:14 +08:00
不如直接输出成 csv 之类的文件(虽然可能开销比转换还大?
|
14
LeeReamond OP @LeeReamond 看了一遍 10#的回复确实有些给人感觉在强调 rust 的优势,但我写的时候只是想表达目前切换到 c++方案下的疑惑,即我不太熟悉如何打通工作链,而且在数据结构方面没什么积累,c++在这方面又不如 rust 直观。并非为特定语言摇旗呐喊,只要能实现需求我对工具持开放态度
|
15
ipwx 2022-05-18 13:43:43 +08:00
@LeeReamond 一般 cmake 就行了。第三方库直接一起丢进来编译就是了。C++ 算法库一般都是模板,而模板库一般都是 header-only ,根本不难编译。pybind11 用 os 自带的就行,apt-get install pybind11-dev python3-dev 然后 cmake FindPackage 就可以了。
|
16
chenxytw 2022-05-18 14:25:24 +08:00
@LeeReamond 最主流的衔接 C++ 和 Python 的工具就是 Cython 和 Pybind11 了,另外就是自己使用 Python C API 封装,但个人不建议,太容易踩坑了,而且是会踩到 Cython/Pybind11 踩过的坑。关于例子,入门通常看 Cython 和 pybind11 的例子就足够了。
实际项目的话,几乎所有用到 Numpy 的计算框架都有 C/C++ 里面处理 numpy 的内容:比如 Tensorflow/PyTorch/Scipy ;一些提供了 Numpy 交互的也有,比如 Arrow 的 Python Binding -> PyArrow 的。 |
17
zhoujinjing09 2022-05-18 14:57:47 +08:00
Numpy 支持 buffer protocol, 可以直接把内存暴露给别的 owner 的。你搜一下相关材料应该常见 ffi 都支持这个
|
18
dayeye2006199 2022-05-19 01:01:35 +08:00 2
这个需求最适合的就是 Apache Arrow 了( https://arrow.apache.org/),设计的初衷就是跨语言的内存数据表达格式,减少 overhead
python 端你需要 pyarrow ,pandas 可以直接转成 arrow 的格式,https://arrow.apache.org/docs/python/pandas.html 然后 rust 端 https://docs.rs/arrow/latest/arrow/ 数据交换的化可以走取决于跨不跨 process ,可以考虑 plasma 内存数据商店 https://arrow.apache.org/blog/2017/08/08/plasma-in-memory-object-store/ 或者 IPC 格式-https://arrow.apache.org/docs/format/Columnar.html#serialization-and-interprocess-communication-ipc 或者走 C Data Interface - https://arrow.apache.org/blog/2020/05/03/introducing-arrow-c-data-interface/ 这几个都是零拷贝的。 |
19
2n80HF9IV8d05L9v 2022-05-19 08:04:36 +08:00 via iPhone
Numba 用了吗
|
20
uni 2022-05-19 12:31:17 +08:00
如果是我的话我会一劳永逸地抛弃 py 全部转向 rust ,比如 pandas 用 polars 替代,numpy 用 ndarray 替代,如果只是常见的通用计算比如协方差什么的都好说
不过其实我也只是口胡,上面说的我都没怎么用过,但是想抛个砖看看能不能引来更多的讨论 |