Ray 在大型(isch)数据集上的低延迟响应
Low-latecy response with Ray on large(isch) dataset
TL;DR
使用 ray 使内存中的 pandas 数据集的加载时间接近零的快速方法是什么?
背景
我正在制作一个使用半大型数据集(pandas 数据帧在 100MB 到 700MB 之间)并试图减少每次查询时间的应用程序。对于我的很多查询,数据加载是响应时间的大部分时间。数据集是优化的镶木地板文件(类别而不是字符串等),它只读取它需要的列。
目前我使用一种天真的方法,每个请求加载需要的数据集(从数据集中读取我需要的 1000 列中的 10-20 列),然后过滤掉我需要的行。
一个典型的请求:
- 读取并解析合约(~50-100 毫秒)
- 加载数据集(10-20 列)(400-1200 毫秒)
- 执行 pandas 操作(~50-100 毫秒)
- 序列化结果(50-100 毫秒)
我现在正在尝试加快速度(减少或删除加载数据集步骤)。
我尝试过的事情:
- 在数据集上使用 Arrow 的新行级过滤,仅读取我需要的行。这可能是未来的好方法,但目前所依赖的新 Arrow Dataset API 比使用旧版加载器读取完整文件要慢得多。
- 优化数据集。这在某种程度上很有效,事物在类别中,数据类型被优化。
- 将数据帧存储在 Ray 中。使用 ray.put 和 ray.get。然而,这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
- 将数据集放入ramfs。这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
- 将对象存储在另一个 Plasma 存储中(ray.put 之外) 但显然速度是一样的(尽管我可能会得到一些其他好处)
数据集是 parquet 文件,这对于 serialization/deserialization 来说已经相当快了。我通常 select 大约 10-20 列(共 1000 列)和大约 30-60% 的行。
关于如何加快加载速度有什么好主意吗?我还没有找到 pandas 数据帧的任何接近零拷贝的操作(即没有序列化惩罚)。
我在想的事情:
将数据集放在一个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 毫秒或更少)。
TL;DR
使用 ray 使内存中的 pandas 数据集的加载时间接近零的快速方法是什么?
背景
我正在制作一个使用半大型数据集(pandas 数据帧在 100MB 到 700MB 之间)并试图减少每次查询时间的应用程序。对于我的很多查询,数据加载是响应时间的大部分时间。数据集是优化的镶木地板文件(类别而不是字符串等),它只读取它需要的列。
目前我使用一种天真的方法,每个请求加载需要的数据集(从数据集中读取我需要的 1000 列中的 10-20 列),然后过滤掉我需要的行。
一个典型的请求:
- 读取并解析合约(~50-100 毫秒)
- 加载数据集(10-20 列)(400-1200 毫秒)
- 执行 pandas 操作(~50-100 毫秒)
- 序列化结果(50-100 毫秒)
我现在正在尝试加快速度(减少或删除加载数据集步骤)。
我尝试过的事情:
- 在数据集上使用 Arrow 的新行级过滤,仅读取我需要的行。这可能是未来的好方法,但目前所依赖的新 Arrow Dataset API 比使用旧版加载器读取完整文件要慢得多。
- 优化数据集。这在某种程度上很有效,事物在类别中,数据类型被优化。
- 将数据帧存储在 Ray 中。使用 ray.put 和 ray.get。然而,这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
- 将数据集放入ramfs。这实际上并没有改善这种情况,因为耗时的部分是数据帧的反序列化。
- 将对象存储在另一个 Plasma 存储中(ray.put 之外) 但显然速度是一样的(尽管我可能会得到一些其他好处)
数据集是 parquet 文件,这对于 serialization/deserialization 来说已经相当快了。我通常 select 大约 10-20 列(共 1000 列)和大约 30-60% 的行。
关于如何加快加载速度有什么好主意吗?我还没有找到 pandas 数据帧的任何接近零拷贝的操作(即没有序列化惩罚)。
我在想的事情:
将数据集放在一个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 毫秒或更少)。