为何Polars在简单列除法运算中速度慢于Pandas?
为什么Polars的元素级除法运算速度只有Pandas的一半?
测试代码与结果
我编写了以下带计时功能的测试代码,对比NumPy、Polars和Pandas的元素级除法运算耗时:
import time import polars as pl import pandas as pd import numpy as np n = 10_000_000 np_arrs = {"x": np.random.rand(n), "y": np.random.rand(n)} pl_df = pl.DataFrame(np_arrs) pd_df = pd.DataFrame(np_arrs) t0 = time.time() z = np_arrs["x"] / np_arrs["y"] t1 = time.time() print(f"time cost: {round((t1 - t0) * 1000)} ms") # 20 ms t0 = time.time() z = pl_df["x"] / pl_df["y"] t1 = time.time() print(f"time cost: {round((t1 - t0) * 1000)} ms") # 42 ms t0 = time.time() z = pd_df["x"] / pd_df["y"] t1 = time.time() print(f"time cost: {round((t1 - t0) * 1000)} ms") # 18 ms
测试结果显示,Polars的运算耗时约为Pandas的两倍,这让我很困惑,想知道背后的原因。
测试环境
- 设备:2020款13英寸MacBook Pro,2GHz 4核i5,16GB内存
- Python版本:3.12.3
- NumPy版本:1.26.4
- Pandas版本:2.2.2
- Polars版本:0.20.31
原因分析
内存布局与存储格式差异
Pandas的DataFrame基于NumPy数组构建,数据默认以连续的C顺序内存块存储,这种布局对单线程元素级运算的缓存友好度很高。而Polars默认使用Arrow列存储格式,虽然适合大数据和并行处理,但在单线程简单运算场景下,Arrow的内存结构可能带来额外的访问或转换开销。运算引擎的设计侧重点
Polars的引擎核心是为复杂查询、并行计算和流式处理优化的,它的调度层在处理简单单线程运算时,会产生额外的框架开销。而Pandas在这类基础运算上直接调用NumPy的高度优化底层实现,中间损耗更少。版本优化差异
你使用的Polars版本0.20.31在单线程简单运算上的优化不如后续版本充分,而Pandas 2.2.2本身对基础运算做了大量底层优化,恰好适配这种场景。懒执行的隐性开销
Polars默认采用懒执行模式,即便这里直接触发了运算,内部的懒执行框架仍可能存在初始化、校验等额外步骤,而Pandas是即时执行,没有这部分损耗。
验证建议
- 升级Polars到最新版本,新版本对单线程基础运算的优化能显著缩小性能差距。
- 测试多线程场景:添加
pl.set_threads(4)后再运行测试,或者设计包含多步骤的复杂查询,此时Polars的并行计算优势会明显体现。 - 扩大数据规模:当数据量超出CPU缓存时,Polars的列存储和高效内存管理会展现出性能优势。
内容的提问来源于stack exchange,提问作者Fei Liu
相关产品推荐
相关产品推荐

