Hub documentation

Оптимизации

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Оптимизации

Мы кратко коснулись различий между ленивой и немедленной оценкой. На этой странице мы покажем, как ленивый API позволяет получить значительный прирост производительности.

Ленивое и немедленное

Polars поддерживает два режима работы: lazy и eager. В eager API запрос выполняется немедленно, тогда как в lazy API запрос вычисляется только тогда, когда он становится «необходимым». Откладывание выполнения до последнего момента может дать значительное преимущество в производительности, поэтому в большинстве неинтерактивных сценариев предпочтительнее использовать lazy API.

Пример

Мы будем использовать пример со страницы выше, чтобы продемонстрировать преимущества производительности при использовании ленивого API. Код ниже вычисляет количество загрузок с archive.org.

Eager

import polars as pl
import datetime

df = pl.read_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)

df = df.select("suffix", "crawl", "date", "tld", "pages", "domains")
df = df.filter(
    (pl.col("date") >= datetime.date(2020, 1, 1)) |
    pl.col("crawl").str.contains("CC")
)
df = df.with_columns(
    (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
)
df = df.group_by("tld", "date").agg(
    pl.col("pages").sum(),
    pl.col("domains").sum(),
)
df = df.group_by("tld").agg(
    pl.col("date").unique().count().alias("number_of_scrapes"),
    pl.col("domains").mean().alias("avg_number_of_domains"),
    pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
).sort("avg_number_of_domains", descending=True).head(10)

Ленивая

import polars as pl
import datetime

lf = (
    pl.scan_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)
    .filter(
        (pl.col("date") >= datetime.date(2020, 1, 1)) |
        pl.col("crawl").str.contains("CC")
    ).with_columns(
        (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
    ).group_by("tld", "date").agg(
        pl.col("pages").sum(),
        pl.col("domains").sum(),
    ).group_by("tld").agg(
        pl.col("date").unique().count().alias("number_of_scrapes"),
        pl.col("domains").mean().alias("avg_number_of_domains"),
        pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
    ).sort("avg_number_of_domains", descending=True).head(10)
)
df = lf.collect()

Время выполнения

Запуск обоих запросов приводит к следующему времени выполнения на обычном ноутбуке с домашним интернет-соединением:

  • Eager: 1.96 секунд
  • Ленивая: 410 миллисекунд

Ленивый запрос выполняется примерно в 5 раз быстрее, чем немедленный. Причина в оптимизаторе запросов: если отложить вызов collect для набора данных до конца, Polars сможет определить, какие столбцы и строки необходимы, и применить фильтры как можно раньше при чтении данных. Для форматов файлов, таких как Parquet, содержащих метаданные (например, min, max в определённой группе строк), разница может быть ещё больше, поскольку Polars способен пропускать целые группы строк на основе фильтров и метаданных, не передавая данные по сети.

Update on GitHub