Ray 在大型(isch)数据集上的低延迟响应

Low-latecy response with Ray on large(isch) dataset

TL;DR

使用 ray 使内存中的 pandas 数据集的加载时间接近零的快速方法是什么?

背景

我正在制作一个使用半大型数据集(pandas 数据帧在 100MB 到 700MB 之间)并试图减少每次查询时间的应用程序。对于我的很多查询,数据加载是响应时间的大部分时间。数据集是优化的镶木地板文件(类别而不是字符串等),它只读取它需要的列。

目前我使用一种天真的方法,每个请求加载需要的数据集(从数据集中读取我需要的 1000 列中的 10-20 列),然后过滤掉我需要的行。

一个典型的请求:

我现在正在尝试加快速度(减少或删除加载数据集步骤)。

我尝试过的事情:

  1. 在数据集上使用 Arrow 的新行级过滤,仅读取我需要的行。这可能是未来的好方法,但目前所依赖的新 Arrow Dataset API 比使用旧版加载器读取完整文件要慢得多。
  2. 优化数据集。这在某种程度上很有效,事物在类别中,数据类型被优化。
  3. 将数据帧存储在 Ray 中。使用 ray.put 和 ray.get。然而,这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
  4. 将数据集放入ramfs。这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
  5. 将对象存储在另一个 Plasma 存储中(ray.put 之外) 但显然速度是一样的(尽管我可能会得到一些其他好处)

数据集是 parquet 文件,这对于 serialization/deserialization 来说已经相当快了。我通常 select 大约 10-20 列(共 1000 列)和大约 30-60% 的行。

关于如何加快加载速度有什么好主意吗?我还没有找到 pandas 数据帧的任何接近零拷贝的操作(即没有序列化惩罚)。

我在想的事情:

  1. 将数据集放在一个actor中,每个线程使用一个actor。这可能会让演员直接访问数据帧而无需任何序列化,但需要我做很多处理:

    • 确保每个线程都有一个演员
    • 按线程分配请求
    • "Recycle" 数据集更新时的参与者

此致, 尼克拉斯

Ray 确实对 pandas 数据帧执行了零拷贝反序列化。反序列化时间基本固定。这里有一些基准

Performing a `ray.get(object_id)` that contains a dataframe

0.8Mb: 
474 µs ± 23.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

80Mb:
507 µs ± 5.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

480Mb:
520 µs ± 3.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我很乐意在 ray community slack

中回答更多问题

在 Slack 上与 Simon 交谈后,我们找到了罪魁祸首:

simon-mo: aha yes objects/strings are not zero copy. categorical or fixed length string works. for fixed length you can try convert them to np.array first

对此进行试验(分类值、固定长度字符串等)让我在使用 Ray Objects 或 Plasma 存储时不能完全获得零复制但至少相当低的延迟(~300 毫秒或更少)。