c 真能比 Python 快这么多?

Hhehepei 2026-06-13 00:34 1

事情是这样的,最近几天在接手别人的一个 python 写的仿真程序,这个程序的运行速度奇慢无比,于是 -m cProfile 看了一眼

检查了一下之后发现程序运行一次大概 500 秒,其中大约有 170 秒都花在一个模拟用的计算函数里了,暂且称其为函数 A 吧

函数 A 大概做了两件事,首先调用了几次函数 B ,去几个表里查表并线性插值,这个过程大概花了 40 秒,这个 40 秒也是优化过的结果了,它原本的算法能干到 500 秒去了。然后就是对大概 30 个参数进行了一系列运算,我大概统计了一下有哪些运算,列表在下面了






























算符 次数
× 30
÷ 5
+ 15
- 10
1

顺便说一下,这个函数传值是用的 np.array ,而且这个函数运行一次其实挺快的,但是被调用的次数实在是多的离谱,所以花的时间就很长了

总之我尝试使用 CPython 重写了一下函数 A 和函数 B ,算法完全没变,想着再怎么样也能把时间减半吧,结果离谱的事情发生了,写完之后-m cProfile 了一下,结果函数耗时 4.8S ,这是不是有点夸张了,c 真能比 python 快这么多?我都开始怀疑我对 cProfile 的使用是不是有什么问题了。

最新回复 (49)
  • wu67 06-13 00:42
    1
    py 是这样的,我对他的印象就是读起来爽写起来爽,但是执行的速度和占用的内存一言难尽
  • lianyue 06-13 00:55
    2
    动态语言都差不多
  • jko123 06-13 01:04
    3
    py 慢是老生常谈的事了
  • woodchen 06-13 01:19
    4
    应该算个别情况吧
  • laminux29 06-13 01:52
    5
    汇编/C/APP 坐一桌,主打性能,劣势是开发效率; Python/Java/PHP/JS 相反。C# 被夹在中间。
  • jark006 06-13 01:57
    6
    C 毕竟是最接近汇编/机器码的 Native 语言,只要写法不太差,基本能榨干 CPU 性能(要是实现地缓存友好,高频调用还能更快)。
    而 Python 这类用解释器运行的脚本语言是很慢的,但我看这差距,170 -> 4.8 ,都 3 个数量级了,不太正常,我猜估计是 Python 的实现的效率不是很高。
    如果这份程序功能基本已固定的话,建议用 AI 重新使用 RUST/C/C++/GO 这类编译型语言实现,性能会高出很多很多
  • jark006 06-13 01:59
    7
    @jark006 如果只能用于 Python 项目,也可以用这几种语言实现这个功能模块,再包装出 Python 接口也行
  • Mac 06-13 02:05
    8
    肯定啊,机器码和解释型的区别,相当于你用翻译机和人比母语。
  • WuSiYu 06-13 02:25
    9
    python 是这样的,你要是高频跑小操作肯定性能比 c 和 jit 语言差远了。不过解决方法也有很多,你这需求大概套个 Numba 的 @njit 就行了,都不用自己写 C

    python 跑计算的正确玩法是调这种加速库,这些库可以从 python ast 中抽取你的运算行为,然后用更高效的代码替代。此时你的 python 运算代码只起到一个描述的作用,真正被执行的已经不是它了
  • billccn 06-13 02:48
    10
    纯数学函数的话直接上 Cython 应该就行了,编译结果应该和 C 差不多快。

    其实 numpy 这一类的库出现的目的就是用 native 函数加速 python 处理,如果用了 numpy 还很慢,那很可能是使用姿势不对,比如在 python 里面对 numpy 对象进行了 iterate 等操作。
  • forisra 06-13 03:58
    11
    ?这不是编译原理的内容吗。
  • msg7086 06-13 04:09
    12
    C 有更多的优化手段,比如 SIMD 化,比如智能内联减少函数调用次数。
    具体优化效果要看具体代码,不过一般而言计算密集型的差距确实会很大的。
    所以一旦开始资源密集型计算,早点切到 Java 或 C++家族才是明智的选择。
  • drymonfidelia 06-13 04:23
    13
    @laminux29 c#的 jit 很强 部分场景甚至能反超 c
  • Cu635 06-13 06:48
    14
    “首先调用了几次函数 B”,几次应该不能算“被调用的次数实在是多的离谱”吧?

    另外,“这个函数传值是用的 np.array”,只有传值使用 numpy ?内部是什么情况呢?

    @laminux29 #5
    /APP ?
  • skinny 06-13 07:35
    15
    Python 就这样,你写 CPU 密集代码特别慢、内存占用特别特别大,实际上写过几种不同语言的实现就知道了,当初我也惊讶内存占用这块怎么差距那么离谱在这吐槽,还有杠精说我不会写代码,但是扒它内存结构就知道内存占用小不了
  • awanabe 06-13 10:03
    16
    大学学语言的时候应该都是基础知识吧
    越接触底层的语言 速度越快

    python 这种动态语言 底层就是 c/c++写的
  • iOCZS 06-13 10:35
    17
    c 的正则都能吊打 Python 的字符串顺序查找
  • ktyang 06-13 10:39
    18
    只从大面上说你的结论是对的,但是具体问题具体分析,这个方法有可能在 py 下或者借助更高效的包也有很多优化潜力。
  • xtreme1 06-13 10:39
    19
    py 的 (实验性) jit 加速比甚至都比同类语言慢一个数量级..
  • AV1 06-13 10:44
    20
    别说跟 C 比了,Python 即使跟同为动态语言的 JS 、PHP 比,都是奇慢无比的。
    动态类型是原因之一,没有 JIT 更会吃大亏。
  • yetrun 06-13 10:56
    21
    CPython 是啥,就不是 python 了吗?
  • henix 06-13 11:02
    22
    考虑到你这个是纯计算,而且 Python 有运算符重载,遇到 + 的时候先要看两个操作数有没有重载 + 运算...后果可想而知
  • Thiece 06-13 11:05
    23
    @yetrun
    是 Python 的一个编程实现,除了 CPython ,还有 Cython 、Pypy 、Nuitka
  • yetrun 06-13 11:07
    24
    @Thiece 那不就是解释器吗?为啥会有 “使用 CPython 重写了一下函数 A 和函数 B” 这一说?
  • Hhehepei 楼主 06-13 11:38
    25
    @Cu635 "被调用次数多得离谱"指的是函数 A ,大概被调用了几百万次
    传值用 numpy ,内部要拆包了进行计算,因为向量的每一个纬度都是不同的参数,至于最开始写这个的人为什么要这么设计,我也不知道
  • Hhehepei 楼主 06-13 11:39
    26
    @yetrun 不好意思,敲错字了,我想说的是 python/c api
  • Hhehepei 楼主 06-13 11:48
    27
    @awanabe 我知道它快,但是没想到能快这么多
    之前一直听说 java jit 之后速度跟 c 差不多,V8 里跑的 js 不比 java 慢什么的。所以一直感觉虽然 python 会慢,但是可能也就几倍差距,结果差这么多是我没想到的。
  • EndlessMemory 06-13 12:45
    28
    c 的速度是 Python 的 100 倍啊
  • laminux29 06-13 14:13
    29
    @Cu635 抱歉,手滑写错了,是 CPP ,不是 APP
  • orlog 06-13 15:24
    30
    脚本语言和编译语言比性能能有什么悬念
  • kneo 06-13 15:27
    31
    @Hhehepei 但你听说的是 java 和 js ,且不说多大水分,和 Python 有什么关系……
  • nsjs 06-13 15:36
    32
    能 jit 的情况肯定快呀,不能的话差 2 个数量级左右也是正常的。如果你会 c 语言方面的底层优化,主要是内存方面的,差 5 个数量级也是正常吧估计
  • wolffy1998 06-13 15:44
    33
    C/C++,Rust 是一档吧,Python 、Eletron 是不是又慢一档。
  • herozzm 06-13 16:11
    34
    py 垃圾的一批,要不是 ai 选了它,早就作古了
  • ClericPy 06-13 17:38
    35
    @kneo 估计是说都是解释型语言,V8 为啥比 CPY 快那么些
  • anivie 06-13 17:47
    36
    @laminux29 #5 java, C#也是能跟 python 坐上一桌了
  • dingyaguang117 06-13 19:14
    37
    @laminux29 Java/C# 有 JIT 和 C 差不多了多少呢~
  • kokutou 06-13 19:52
    38
    把 py 代码发给 ai 问问,是不是在不停搬运内存
  • Cu635 06-13 20:08
    39
    @Hhehepei #26 @yetrun #21 @Thiece #23
    确认一下,是不是 Cython 这个东西?(我也是后续搜索知道的这个,现在才过来猜测的)。注意 Cython 不是 CPython
    或者再猜测一个,也许用的是 pybind11 ?
  • BeiChuanAlex 06-13 20:15
    40
    真是世道变了,居然还有人敢质疑 C 的速度?过几年是不是有人要质疑 汇编 的速度了?😂
  • catazshadow 06-13 20:18
    41
    毕竟胶水语言
  • qiuyuxiao 06-13 21:36
    42
    这种事情在 Python 还没流行的时候就已经有了定论了。
    你的测试非常准确。Python 怕的不是计算,而是『高频调用小函数』和『高频创建 NumPy 小数组』。你用 C API 把这些高频的胶水开销全部干掉了,4.8 秒是 C 语言应有的真实物理实力。

    想起当年儿子要学信息学奥赛问我是 C 还是 Python ,我说,你去问你们指导老师,他如果回答说不是 C ,咱们就换地方。
  • IamUNICODE 06-13 23:20
    43
    我记得 python 在解释型语言里甚至都是最差的...
  • James369 06-13 23:30
    44
    C 是面向机器的语言,Python 是面向人的语言。各有优势
  • chenY520 06-14 00:04
    45
    你要想,py 不是 c 写的吗?
  • Hhehepei 楼主 06-14 00:10
    46
    @Cu635 不是 Cython ,是用 Python/C API 写的 CPython Moudle ,需要#include <Python.h>,然后满足它的一堆奇怪接口,最后编译成模块。
    查了一下 pybind11 ,感觉要简单好多,早知道用 pybind11 了,不过写都写完了。。。
  • Cu635 06-14 00:28
    47
    @Hhehepei #46
    你这本质上是自己实现了一个超小型极简化的 pybind11 啊……
  • vicalloy 06-14 10:20
    48
    python 的循环比 C 慢不止一个数量级。涉及大量的数值运算,优先考虑 numpy ,然后是用 C 或 rust 写扩展。
  • apoclast 06-14 11:30
    49
    开发效率和执行效率二选一
* 帖子来源V2EX
返回