常用作图脚本

准备一套作图脚本供日后使用。目标包括:

  • tikz 的风格统一
  • 文字数据可选中
  • 矢量图,放缩无损
  • 直出 pdf

条形图预览

{"config": {"view": {"continuousWidth": 400, "continuousHeight": 300}}, "data": {"name": "data-90c5cf575d993e0ad54f896cfbb5c8e6"}, "mark": {"type": "bar", "height": 12, "opacity": 0.9, "stroke": "black", "strokeWidth": 0.382}, "encoding": {"color": {"field": "GPU", "legend": {"labelFont": "serif", "titleFont": "serif"}, "scale": {"scheme": "pastel1"}, "sort": ["K40", "P100", "V100", "A100", "H100"], "type": "nominal"}, "x": {"axis": {"labelFont": "serif", "titleFont": "serif"}, "field": "L1", "title": "L1D+SMEM/KB/SM", "type": "quantitative"}, "y": {"axis": null, "field": "GPU", "sort": ["K40", "P100", "V100", "A100", "H100"], "type": "nominal"}}, "$schema": "https://vega.github.io/schema/vega-lite/v4.17.0.json", "datasets": {"data-90c5cf575d993e0ad54f896cfbb5c8e6": [{"GPU": "K40", "L1": 64, "L2": 1536}, {"GPU": "P100", "L1": 64, "L2": 4096}, {"GPU": "V100", "L1": 128, "L2": 6144}, {"GPU": "A100", "L1": 192, "L2": 40960}, {"GPU": "H100", "L1": 256, "L2": 51200}]}}

折线图预览

{"config": {"view": {"continuousWidth": 400, "continuousHeight": 300}, "axisX": {"tickMinStep": 50}, "axisY": {"tickMinStep": 10000}}, "layer": [{"mark": "line", "encoding": {"text": {"field": "GPU", "type": "nominal"}, "x": {"field": "L1", "scale": {"domain": [50, 250]}, "title": "L1D+SMEM/KB/SM", "type": "quantitative"}, "y": {"field": "L2", "scale": {"domain": [0, 50000]}, "title": "L2/KB", "type": "quantitative"}}}, {"mark": {"type": "text", "align": "left", "baseline": "middle", "dx": 5, "dy": 5}, "encoding": {"text": {"field": "GPU", "type": "nominal"}, "x": {"field": "L1", "scale": {"domain": [50, 250]}, "title": "L1D+SMEM/KB/SM", "type": "quantitative"}, "y": {"field": "L2", "scale": {"domain": [0, 50000]}, "title": "L2/KB", "type": "quantitative"}}}], "data": {"name": "data-90c5cf575d993e0ad54f896cfbb5c8e6"}, "height": 300, "width": 400, "$schema": "https://vega.github.io/schema/vega-lite/v4.17.0.json", "datasets": {"data-90c5cf575d993e0ad54f896cfbb5c8e6": [{"GPU": "K40", "L1": 64, "L2": 1536}, {"GPU": "P100", "L1": 64, "L2": 4096}, {"GPU": "V100", "L1": 128, "L2": 6144}, {"GPU": "A100", "L1": 192, "L2": 40960}, {"GPU": "H100", "L1": 256, "L2": 51200}]}}

脚本

import altair as alt  # tested on altair==4.2.0 && altair==5.2.0
from vl_convert import vegalite_to_pdf  # tested on vl-convert-python==1.3.0
import sys


def draw_line(data):
    chart = alt.Chart(alt.InlineData(data)).encode(
        x=alt.X(
            "L1",
            type="quantitative",
            title="L1D+SMEM/KB/SM",
            scale=alt.Scale(domain=(50, 250)),
        ),
        y=alt.Y(
            "L2",
            type="quantitative",
            title="L2/KB",
            scale=alt.Scale(domain=(0, 50000)),
        ),
        text=alt.Text("GPU", type="nominal"),
    )

    chart = chart.mark_line() + chart.mark_text(
        align="left", baseline="middle", dx=5, dy=5
    )

    chart = (
        chart.configure_axisY(tickMinStep=10000)
        .configure_axisX(tickMinStep=50)
        .properties(width=400, height=300)
    )

    chart.save("gpu-evole.line.html")
    open("gpu-evole.line.pdf", "wb").write(vegalite_to_pdf(vl_spec=chart.to_json()))


def draw_bar(data):
    sortGPU = [it["GPU"] for it in data]
    chart = alt.Chart(alt.InlineData(data)).encode(
        x=alt.X(
            "L1",
            type="quantitative",
            title="L1D+SMEM/KB/SM",
            axis=alt.Axis(labelFont="serif", titleFont="serif"),
        ),
        y=alt.Y("GPU", type="nominal", sort=sortGPU, axis=None),
        color=alt.Color(
            "GPU",
            type="nominal",
            sort=sortGPU,
            scale=alt.Scale(scheme="pastel1"),
            legend=alt.Legend(labelFont="serif", titleFont="serif"),
        ),
    )
    chart = chart.mark_bar(
        opacity=0.9, stroke="black", strokeWidth=1 - 0.618, height=12
    )

    chart.save("gpu-evole.bar.html")
    open("gpu-evole.bar.pdf", "wb").write(vegalite_to_pdf(vl_spec=chart.to_json()))


def main(*argv):
    data = [
        {"GPU": "K40", "L1": 64, "L2": 1536},
        {"GPU": "P100", "L1": 64, "L2": 4096},
        {"GPU": "V100", "L1": 128, "L2": 6144},
        {"GPU": "A100", "L1": 192, "L2": 40960},
        {"GPU": "H100", "L1": 256, "L2": 51200},
    ]

    draw_line(data)
    draw_bar(data)

    return 0


if __name__ == "__main__":
    sys.exit(main(*sys.argv))