Hub documentation

Optimizaciones

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Optimizaciones

Mencionamos brevemente la diferencia entre la evaluación perezosa (lazy) y la evaluación inmediata (eager). En esta página mostraremos cómo la API perezosa (lazy) puede utilizarse para obtener enormes beneficios de rendimiento.

Lazy vs Eager

Polars admite dos modos de operación: lazy y eager. En la API eager, la consulta se ejecuta de inmediato, mientras que en la API lazy, la consulta solo se evalúa cuando es «necesaria». Diferir la ejecución hasta el último momento puede tener ventajas de rendimiento significativas, y por eso la API lazy se prefiere en la mayoría de los casos no interactivos.

Ejemplo

Utilizaremos el ejemplo de la página anterior para mostrar las ventajas de rendimiento de usar la API perezosa. El código de abajo calculará el número de cargas desde 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)

Perezoso

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()

Tiempos

Ejecutar ambas consultas da como resultado los siguientes tiempos de ejecución en un portátil normal con una conexión a internet doméstica:

  • Eager: 1.96 segundos
  • Perezoso: 410 milisegundos

La consulta perezosa es ~5 veces más rápida que la inmediata. La razón es el optimizador de consultas: si retrasamos la collect de nuestro conjunto de datos hasta el final, Polars podrá razonar sobre qué columnas y filas se requieren y aplicar los filtros lo antes posible al leer los datos. Para formatos de archivo como Parquet que contienen metadatos (p. ej., min, max en un cierto grupo de filas), la diferencia puede ser aún mayor, ya que Polars puede omitir grupos de filas completos basándose en los filtros y los metadatos sin enviar los datos a través de la red.

Update on GitHub