3

如何提高 Python 数组操作性能.

 1 year ago
source link: https://www.v2ex.com/t/882441
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  Python

如何提高 Python 数组操作性能.

  jeeyong · 3 小时 29 分钟前 · 796 次点击
最近正在写一个小系统. 涉及到把 CT 影像转换成 PNG.
CT 影像不是不是标准通用格式, 所以需要从读取 bytes 再转成数组..
这个过程中需要两次处理数组数据, 但是性能很慢..有相关经验的朋友可以给点建议嘛?
以下是详述:

我读出来的 bytes 数据处理成 uint8 后. 是这样的形式:
[208, 4, 208, 4, 208, 4...196, 8]
不懂图像处理的知识, 我的理解就是, 一个灰度, 一个 Alpha 通道值(透明值?).
第一次处理数组是要把上面的数组, 改成如下形式: <- 暂且叫 生成数组阶段.
[208, 208, 208, 4, 208, 208, 208, 4.......]
就是把 208 这个灰度值变成 rgb 的形式.
然后再通过一个循环变成 pillow 支持的格式, 如下: <- 暂且叫 数组转换阶段吧.
[
[ [r, g, b, a], [r, g, b, a], [r, g, b, a], ],
[ [r, g, b, a], [r, g, b, a], [r, g, b, a], ],
[ [r, g, b, a], [r, g, b, a], [r, g, b, a], ],
]

然后这个数组要通过 numpy 转换成 uint8 类型才能提交给 pillow 或者类似图片处理的库..

所以大致耗时分为三个阶段:
1. 生成数组
2. 转换数组
3. 通过 numpy 转换数组类型为 uint8.

数组大小为: 5022 * 4200 * 4 = 84,369,600

环境 A 介绍:
Win10, 10900K, 64GB 3600, NVME 2TB SSD
Python 3.10.4, pillow 最新版
阶段一耗时: 9 秒左右
阶段二耗时: 45 秒左右
阶段三耗时: 5 秒左右

觉得太慢, 尝试全部改成 numpy 操作.
但是阶段二慢的出奇, 后来查资料发现, numpy 在大量数组下标赋值操作的性能还不如 Python 原生 list.
阶段二, 上厕所, 洗把脸回来还没跑完, 就直接放弃了. 也尝试过 np.insert 操作, 一样慢.

后来尝试环境 B, 基于 pypy 的.
pypy3.8, numpy, pillow, 同样的硬件.
第一阶段耗时: 0.2 秒
第二阶段耗时: 9.7 秒
第三阶段耗时: 77 秒
查阅资料得知, pypy 的 C 扩展接口性能很差, 不如原生 python.
而 Numpy 就是 C 扩展的库..所以导致 Numpy 性能急剧下降.

好了..剩下的办法超出我的知识范畴了..
有朋友能分享一下经验或者给个可能的方向我去看也行.

需要转换的数据量大约有 23 万个 CT 文件. 按照一个文件 1 分钟, 我即便 4 个进程跑(文件转换的服务器 4 核 8GB 内存, 还要跑一些其他服务.), 5 万分钟 / 60 分钟 / 24 小时 一点意外没有的情况要跑 42 天...

顺便吐槽以下, 朋友给写了个 nodejs 的版本, 转换一个图 2.3 秒, WTF!!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK