Polars 比 NumPy 慢吗?

6

我在考虑在一个解析问题中使用polars代替numpy,将结构化文本文件转换为字符表并对不同列进行操作。然而,似乎在我执行的大多数操作中,polarsnumpy慢了约5倍。我想知道这是为什么,以及是否有什么我做错了,因为polars应该更快。

例如:

import requests
import numpy as np
import polars as pl

# Download the text file
text = requests.get("https://files.rcsb.org/download/3w32.pdb").text

# Turn it into a 2D array of characters
char_tab_np = np.array(file.splitlines()).view(dtype=(str,1)).reshape(-1, 80)

# Create a polars DataFrame from the numpy array
char_tab_pl = pl.DataFrame(char_tab_np)

# Sort by first column with numpy
char_tab_np[np.argsort(char_tab_np[:,0])]

# Sort by first column with polars
char_tab_pl.sort(by="column_0")

Jupyter中使用%%timeitnumpy排序大约需要320微秒,而polars排序大约需要1.3毫秒,即慢了约五倍。

我还尝试了char_tab_pl.lazy().sort(by="column_0").collect(),但对持续时间没有影响。

另一个例子(获取第一列等于'A'的所有行):

# with numpy
%%timeit
char_tab_np[char_tab_np[:, 0] == "A"]

# with polars
%%timeit
char_tab_pl.filter(pl.col("column_0") == "A")

再次测试发现,numpy 耗时 226 微秒,而 polars 耗时 673 微秒,慢了三倍左右。

更新

根据评论中的建议,我尝试了两个方法:

1. 将文件增大1000倍,观察是否能在更大的数据上提高 polars 的性能。

结果:时间仍旧是 numpy 快约2倍(1.3毫秒对比2.1毫秒)。此外,创建字符数组需要的时间是 numpy 约2秒钟,而 polars 需要约2分钟才能创建数据帧,即慢了60倍。

要复制,请在上面的代码中创建 numpy 数组之前添加 text *= 1000

2. 将数据转换为整数类型。

对于原始(较小)文件,将其转换为整数可以加快numpypolars的处理速度。在numpy中进行的过滤仍然比polars快约5倍(30微秒对120微秒),而排序时间变得更加相似(numpy为150微秒,polars为200微秒)。

然而,对于大文件,polars略快于numpy,但巨大的实例化时间只有在数据框需要被查询数千次时才值得使用。


我不确定你为什么期望极坐标比numpy数组更快。但它确实比pandas更快,这也是它的设计初衷。 - Pranav Hosangadi
@PranavHosangadi 我认为 Polars 可以在多个核心上并行运行,而 Numpy 则是单线程的,因此它的速度应该大约是{核心数}倍于 Numpy? - Qunatized
2
请注意,polars使用其Utf8数据类型处理此内容,该类型支持任意长度的Unicode字符串。这可能会产生一些开销。我发现将每个字符转换为int可以将polars速度提高5倍:char_tab_np = np.array(text.splitlines()).view(dtype='|U1').view(np.int32).astype(np.uint8).reshape(-1,80) - Nick ODell
调用多线程程序总会有开销。这包括启动线程的成本、等待它被调度的成本和等待它完成的成本。对于足够长的程序,这种开销被并行处理所抵消。但对于短程序来说,这种开销就占主导地位。 - Nick ODell
@NickODell 你是对的;转换为int确实加快了进程,但是对于numpy和polars都是如此,所以polars仍然比numpy慢大约5倍。在我的电脑上,numpy在转换后大约需要30微秒,而polars需要135微秒。 - Qunatized
显示剩余3条评论
1个回答

3

Polars在过滤不必要的字符串数据时会执行额外的工作。Polars使用arrow large-utf8缓冲区来存储其字符串数据。这使得过滤比过滤Python字符串/字符(例如指针或u8字节)更加昂贵。

有时候值得这样做,有时候则不值得。如果您的数据是同质的,那么numpy比polars更适合。如果您的数据是异构的,polars很可能会更快。特别是如果您考虑整个查询而不是这些微基准。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接