Polars中pl.when().then().otherwise()性能偏慢的原因及适用场景咨询
Python Polars中pl.when().then().otherwise()的性能疑问
测试场景与数据构造
构造了包含3000万行UInt64类型数据的DataFrame,代码如下:
from random import randint import polars as pl df = pl.DataFrame({ 'A': [randint(1, 10**15) for _ in range(30_000_000)], 'B': [randint(1, 10**15) for _ in range(30_000_000)], }, schema={ 'A': pl.UInt64, 'B': pl.UInt64, })
性能测试结果
- 使用
pl.min_horizontal实现横向取最小值:92.4 ms ± 16.3 ms/循环 - 使用
pl.when().then().otherwise()实现相同逻辑:458 ms ± 75.9 ms/循环 - 单独执行比较操作
pl.col('A') < pl.col('B'):49.2 ms ± 6.23 ms/循环 - 移除
otherwise()后的pl.when().then():664 ms ± 19.7 ms/循环 - 其他横向聚合方法(如
pl.reduce、pl.fold)均显著快于pl.when().then()
问题解答
1. 该性能表现是否为预期行为?
是预期行为。Polars针对min_horizontal这类特定横向聚合函数做了专门的批量优化,而when/then/otherwise是通用分支逻辑,没有针对这类简单聚合场景做特殊适配,性能差距属于正常现象。
2. 为何pl.when().then()比其他表达式慢很多?
主要有三个核心原因:
- 分支逻辑的额外开销:
when/then/otherwise本质是逐行判断分支后执行值选择,相比min_horizontal这类直接对整列内存块做批量运算的操作,需要处理大量分支跳转指令,CPU开销更高。 - 缺少针对性优化:横向聚合函数底层会用SIMD指令、连续内存遍历等高效方式处理数据,而
when/then/otherwise要兼容各种复杂分支场景,无法做这类针对性的批量优化。 - 缓存命中率差异:分支逻辑可能导致内存访问不连续,破坏CPU缓存的局部性;而横向聚合的内存访问是连续的,缓存命中率更高,执行效率自然更好。
3. 哪些场景下应避免使用when().then().otherwise()?
- 简单横向聚合场景:比如取多列最大/最小值、求和等,直接用
min_horizontal、max_horizontal这类专用函数,性能提升明显。 - 大规模数据分支判断:处理千万级以上行数据时,若能用向量化操作替代分支逻辑,就不要用
when/then/otherwise。比如用pl.col().clip()替代范围判断分支,用pl.coalesce()替代空值判断分支。 - 可被数学运算简化的逻辑:比如
when(A>B).then(A).otherwise(B)等价于取两列最大值,完全可以用max_horizontal替代,这类场景专用函数比分支表达式高效得多。
内容的提问来源于stack exchange,提问作者s-b90
相关产品推荐
相关产品推荐

