Python 调用 Rust 挺香的,向没用过的朋友们安利一下 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LeeReamond
V2EX    问与答

Python 调用 Rust 挺香的,向没用过的朋友们安利一下

  •  2
     
  •   LeeReamond 2021-03-01 12:12:35 +08:00 3976 次点击
    这是一个创建于 1743 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简单说一下吧,python 语言效率的问题也是老生常谈了,我也是 v2 上 py 社区的老面孔了

    rust 这门语言我没接触过,我对他的印象一直是那种想要干掉老语言的新语言,但是生态不行所以没戏。印象中 rust 是对标 c/c++,scala 对标 java,julia 对标 python,再加一个专门写网络服务的 go,这似乎就是新时代的样貌了。但是其实这四门语言除了 go 以外都几乎没接触过。

    直到前几天跟朋友聊天,对方偶然说起 python 调用 rust 可以是一种解决方案。我正好也面临计算密集任务的困扰,就去搜了一下,一搜,发现据说很香,于是试用了一下,发现真的很香,一直香到爆炸了,我就来 v2 发帖了。

    =================================

    先说一下直观效果,团队现在在做数据类服务,有很多密集计算型任务,并且以后可能越加越多。刚开始写的时候肯定是 python 实现算法,但是随着数据量增多,算法变复杂,处理时间成几何倍数增加,py 已经顶不住了。所以我们之前是把一些最集中的部分先用 c++抽出来写成插件,因为我和另外一个朋友都能写点简单的 c++,这么暂时先凑合着,原计划是要用 cython 把算法部分完全重写的。

    前天听说 rust 能用,当天花了几个小时过了一遍 rust 的语法,昨天把 c++的东西用 rust 完全重写了一遍,大概一千多行,今天已经上测试服务器了。并且简单跑了一下分,rust 嵌入 python 表现非常优秀。

    我们重复执行同一个计算任务,原任务用 python 实现大概耗时在一分多钟,切换到 c++之后大概耗时在 3100 毫秒,今天改写成 rust 之后,在实现基本上完全相同的情况下,单次执行时间缩短到了 2300 毫秒左右,令人很惊喜。

    而之后多线程压力测试中,1600 次任务,c++版本耗时 720 秒,rust 版本耗时 440 秒。这个差距相对于单核进一步拉大,似乎数据中转和线程调度上,相对于 cython 还有进一步的优势。

    =================================

    所以我在这里向所有在 python 任务中遇到 cpu 密集型任务瓶颈的朋友们推荐 rust 这门语言和它配套的 python 嵌入方案。目前看来几天的使用里,它可能带来的问题并不多。我们测试中遇到的为数不多的问题是似乎底层调用机制与 cython 的嵌入不同。单纯测试空函数返回时间,如果使用 cython 编译 python 函数,是可以加速函数返回的,但使用 rust 嵌入方案的话却会让返回时间减慢一倍左右。我个人也不是很了解解释器调用的实现细节,这个暂且不谈。不过只要不做特别细粒度的嵌入,这其实也不会造成什么困扰。

    而与问题相对的,好处就很多了。

    rust 的好处其一是它的性能强,与原生 C 比肩,并且显然在实际生产中比 c 更快。因为一般用 c++也就是用 stl 中的容器和算法搞一搞,我个人比较菜,不太有水平自己实现。在这种条件下,rust 的内置实现的几种数据结构和算法,是比 c++stl 更快的,起到了实际上性能领先的作用。

    其二是 rust 的学习曲线非常平滑,本身通过限制语法自由度,在设计上屏蔽了 c++中一些让人非常头秃的一些特性(野指针之类的),加上有比较完善的内建通用数据结构,导致如果你只是单纯的实现算法的话,向我们一样简单学习几小时就直接可以工作了。并且同样由于编译器要求严格,你写出的代码只要能过编译,一般质量都还可以。

    第三是 rust 的工程化很香。之前用 cython 方案,其实整个目录结构工程化不是很好做,因为 cython 这门介于 c 和 py 之间的语言,说不好听点是四不像,很多似是而非的坑需要自己踩,通常是 c 的方法也不行,py 的方法也不行,只能按照 cython 独有的规矩。这点切换到 rust 之后就不构成烦恼,因为原生模块化方案还不错,嵌入 py 时可以非常接近 py 工程目录的逻辑结构,整个代码解耦非常舒服。

    第四是 rust 这门语言描述能力比较强,毕竟是一门十年左右的新语言,在编程语言大家庭中算孙子辈的了。像我们平常使用 python 的原因之一可能就是因为 py 的描述能力强大,相比之下如果用纯 c 语言写东西的话就会感觉在描述能力上束手束脚。而切换到 rust 则不会有明显的不适感,虽然相对于动态的 python 确实受到了诸多限制,但是本身语言也吸收了这么多年优秀语言的优秀特性,也加入了很多语法糖,比如下述代码实现的逻辑

    fn main() { let list = vec![1 , 2 , 3 , 4 , 5]; for i in 0..list.len() { println!("num: {}" , list[i]) } } 

    即使你从未学习过 rust 的代码,你也会发现基本上能看懂,并且这种语言在基础使用场景的描述能力并不弱,已经十分接近自然语言逻辑。

    ======================================

    总之胡言乱语写了这么多,与大家分享,已经很熟悉这套工具链的朋友请勿喷,我相信还有很多和我一样不了解的朋友,欢迎探讨,我们共同进步。

    14 条回复    2024-03-12 16:33:57 +08:00
    shoaly
        1
    shoaly  
       2021-03-01 12:25:31 +08:00
    越来越多的场景 会是多语言互相 协同, 利用各自优势吧...
    shoaly
        2
    shoaly  
       2021-03-01 12:45:49 +08:00
    对了 ,老哥有没有比较过 rust 和 go 的时间
    jokaye
        3
    jokaye  
       2021-03-01 12:58:14 +08:00
    for i in 0..list.len() 哎这语法糖一言难尽
    LeeReamond
        4
    LeeReamond  
    OP
       2021-03-01 13:14:54 +08:00 via Android
    @shoaly 我不会用 python 调 go,没研究过。不过单纯语言性能的话你可以在网上搜到其他的跑分。一般来说同样逻辑 rust 肯定比 go 快,可能快几到几十百分点这样,没有数量级差距。因为 go 有 gc 而 rust 没有,但是 rust 香就香在它没有 gc 一样做到了你开发时候不需要自己考虑回收的问题
    LeeReamond
        5
    LeeReamond  
    OP
       2021-03-01 13:17:42 +08:00 via Android
    @jokaye 挺好的啊,不知道有啥一言难尽的,我写了一千行 rust 以后感觉挺香的。毕竟 for 太常用了,像 js 那种进入 es6 以后 for 的语法大幅简化,但还是要比这种写法多写不少字。rust 这个语法的优化接近 python 了,你甚至不需要考虑 i 从哪来的问题,写码的时候能体会到一种显著的对心智负担的降低
    itskingname
        6
    itskingname  
       2021-03-01 13:39:54 +08:00
    @shoaly Python 调用 Golang 可以看这篇文章: https://mp.weixin.qq.com/s/H1Fe7BXdKIeEzIxjLxlYBg
    Kilerd
        7
    Kilerd  
       2021-03-01 15:33:34 +08:00
    要不是看到这 for i in 0..list.len(), 我差点就以为你懂 rust 了。
    F281M6Dh8DXpD1g2
        8
    F281M6Dh8DXpD1g2  
       2021-03-01 15:35:46 +08:00   1
    我猜你的 python 算法肯定是 numpy 和原生类型混用的
    wzb0909
        9
    wzb0909  
       2021-03-01 15:50:58 +08:00
    Jirajine
        10
    Jirajine  
       2021-03-01 16:05:51 +08:00 via Android
    rust 对标 cpp,提供零运行时开销的、尽可能多的抽象和各种特性。
    julia 对标 c,保持简单、手动内存管理、无宏、无隐式的调用和分配。
    joApioVVx4M4X6Rf
        11
    joApioVVx4M4X6Rf  
       2021-03-01 20:25:57 +08:00
    话说 python 怎么和 rust 通信的呀,可以发个链接学习学习吗
    hsfzxjy
        12
    hsfzxjy  
       2021-03-01 21:33:41 +08:00 via Android
    楼主是用 pyo3 吗
    LeeReamond
        13
    LeeReamond  
    OP
       2021-03-02 03:41:15 +08:00 via Android   1
    @hsfzxjy
    @Jirajine pyo3 很好,gh 直接用就是了。rust 也有 c 编译的方式在 py 里用 ctypes 调,但是这类通信最难解决的是类型转换问题,所以还是有转换的第三方香
    runstone
        14
    runstone  
       2024-03-12 16:33:57 +08:00
    楼主用的 pyo3 去结合的么?还是别的什么工具。这里面需要注意的是 python 的整数和 float 都是无穷大的,对应 rust 没有相应的类型啊,要怎么搞?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3493 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 21ms UTC 04:30 PVG 12:30 LAX 20:30 JFK 23:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86