对标 cuSpatial#

本仓库中基准测试的目标是衡量各种 cuSpatial API 的性能。cuSpatial 中的基准测试使用 pytest-benchmark 插件编写,该插件基于 pytest Python 测试框架。使用 pytest-benchmark 为熟悉 pytest 的开发者提供了无缝的体验。我们包含了公共 API 和内部函数的基准测试。前者提供了我们性能的宏观视图,尤其是与 geopandas 相比。后者帮助我们量化并最小化 Python 绑定的开销。

注意

我们目前的基准测试完全侧重于测量运行时间。然而,对于某些情况,最小化内存占用同样重要。未来,我们可能会更新基准测试,以包含内存使用测量。

基准测试组织#

顶层基准测试分为 internalAPI 目录。API 基准测试用于用户期望使用的公共功能。内部基准测试衡量 cuSpatial 内部构件的性能,这些构件没有稳定性保证。

在每个目录中,基准测试根据函数类型进行组织。cuSpatial 中的函数通常分为两类:

  1. GeoDataFrameGeoSeries 等类的方法。

  2. 对上述类进行操作的自由函数,如 cuspatial.from_geopandas

前者应组织到名为 bench_class.py 的文件中。例如,GeoDataFrame.sjoin 的基准测试属于 API/bench_geodataframe.py。基准测试应尽可能以类层次结构的最高层级进行编写。例如,所有类都支持 take 方法,因此这些基准测试属于 API/bench_frame_or_index.py

注意

pytest 不支持存在两个同名的基准测试文件,即使它们位于不同的目录中。因此,公共类的内部方法的基准测试文件会以 _internal 为后缀。例如,GeoDataFrame.polygons.xy 的基准测试属于 internal/bench_geodataframe_internal.py

自由函数具有更大的灵活性。总的来说,它们应该被分组到包含相似功能的基准测试文件中。例如,I/O 基准测试都可以放在 io/bench_io.py 中。目前这些分组由开发者自行决定。

运行基准测试#

默认情况下,pytest 会发现以 test_ 为前缀的测试文件和函数。对于基准测试,我们将 pytest 配置为使用 bench_ 前缀进行搜索。安装 pytest-benchmark 后,运行基准测试就像直接运行 pytest 一样简单。

当运行基准测试时,默认行为是将结果以表格形式输出到终端。一个常见的需求是比较更改前后的基准测试性能。我们可以使用 pytest 的 --benchmark-autosave 选项保存输出,从而生成这些比较。使用此选项时,基准测试运行后,输出中将包含一行

Saved benchmark data in: /path/to/XXXX_*.json

XXXX 是一个四位数字,用于标识基准测试。如果愿意,用户也可以使用 --benchmark-save=NAME 选项,它允许对结果文件名进行更多控制。给定两次基准测试运行 XXXXYYYY,可以使用以下命令比较基准测试:

pytest-benchmark compare XXXX YYYY

请注意,比较使用的是 pytest-benchmark 命令而不是 pytest 命令。pytest-benchmark 有许多额外的选项可用于自定义输出。下一行包含一个有用的示例,但开发者应进行实验以找到有用的输出方式

pytest-benchmark compare XXXX YYYY --sort="name" --columns=Mean --name=short --group-by=param

更多详细信息,请参阅 pytest-benchmark 文档

基准测试内容#

编写基准测试#

就像基准测试应该以层次结构中最高层级的类来编写一样,它们也应该尽可能少地假定数据的性质。

与 geopandas 比较#

随着 cuSpatial API 的成熟,我们将从性能角度将其与匹配的 geopandas 函数进行比较。

测试基准测试#

基准测试需要与 cuspatial 中的 API 更改保持同步更新。当前的基准测试集是针对一小组测试数据的调试基准测试。我们的 CI 测试利用这一点来确保基准测试仍然是有效的代码。

性能分析#

虽然并非严格属于我们的基准测试套件,但性能分析是一个常见的需求,因此我们在此提供一些指南。以下是两种简单的(可能有其他)对基准测试进行性能分析的方法:

  1. pytest-profiling 插件。

  2. py-spy 包。

使用前者就像在 pytest 调用中添加 --profile (或 --profile-svg) 参数一样简单。后者则需要从 py-spy 调用 pytest,如下所示:

py-spy record -- pytest bench_foo.py

每种工具都有不同的优势,并提供略有不同的信息。开发者应该尝试这两种工具,看看哪种更适合特定的工作流程。也鼓励开发者分享他们发现的有用的替代方法。