-
Notifications
You must be signed in to change notification settings - Fork 193
feat: add a ci gpu compress benchmark #8951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
846dac3
3ce6c56
8cdd1b1
fa6c0ba
ad8bd5f
f729318
fde95c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # Runs the GPU-enabled compression decompression benchmarks for a pull request. | ||
| # Called from bench-dispatch.yml when the `action/benchmark-gpu-compress` label is added. | ||
|
|
||
| name: GPU Compression Benchmarks | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||
| cancel-in-progress: false | ||
|
|
||
| on: | ||
| workflow_call: { } | ||
| workflow_dispatch: { } | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| gpu-compress-bench: | ||
| name: GPU Compression | ||
| timeout-minutes: 120 | ||
| runs-on: >- | ||
| runs-on=${{ github.run_id }}/family=g5/cpu=8/image=ubuntu24-gpu-x64/extras=s3-cache/tag=gpu-compress-bench | ||
| steps: | ||
| - uses: runs-on/action@v2 | ||
| with: | ||
| sccache: s3 | ||
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | ||
| - name: Setup benchmark environment | ||
| run: sudo bash scripts/setup-benchmark.sh | ||
| - uses: ./.github/actions/setup-rust | ||
| with: | ||
| repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
| enable-sccache: "true" | ||
| - uses: ./.github/actions/system-info | ||
| - name: Display NVIDIA GPU details | ||
| run: | | ||
| nvidia-smi | ||
| nvidia-smi -L | ||
| nvidia-smi -q -d Memory | ||
| - name: Build GPU compression benchmark | ||
| shell: bash | ||
| run: | | ||
| cargo build --locked --package compress-bench --profile release_debug --features cuda,unstable_encodings | ||
| - name: Run GPU compression benchmark | ||
| shell: bash | ||
| env: | ||
| RUST_BACKTRACE: full | ||
| # Do not enable VORTEX_EXPERIMENTAL_PATCHED_ARRAY here: it rewrites interior | ||
| # `Patches` into a top-level `vortex.patched` array, which has no CUDA decode | ||
| # kernel and makes GPU decompression fail with "No CUDA kernel for encoding | ||
| # vortex.patched". Leaving it unset keeps patches inline in the bitpacked array, | ||
| # which the CUDA bitpacked kernel decodes. This matches the GPU test workflow | ||
| # (cuda.yaml), which also sets only FLAT_LAYOUT_INLINE_ARRAY_NODE. | ||
| FLAT_LAYOUT_INLINE_ARRAY_NODE: "1" | ||
| run: | | ||
| bash scripts/bench-taskset.sh target/release_debug/compress-bench \ | ||
| --gpu-decompress -d table > gpu-compress.txt | ||
| cat gpu-compress.txt | ||
| - name: Publish results | ||
| shell: bash | ||
| run: | | ||
| { | ||
| echo "# GPU Compression" | ||
| echo | ||
| echo '```text' | ||
|
joseph-isaacs marked this conversation as resolved.
|
||
| cat gpu-compress.txt | ||
| echo '```' | ||
| } > comment.md | ||
| cat comment.md >> "$GITHUB_STEP_SUMMARY" | ||
| - name: Comment PR | ||
| if: github.event.pull_request.head.repo.fork == false | ||
| uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3 | ||
| with: | ||
| file-path: comment.md | ||
| comment-tag: bench-pr-comment-gpu-compress | ||
| - name: Comment PR on failure | ||
| if: failure() && github.event.pull_request.head.repo.fork == false | ||
| uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3 | ||
| with: | ||
| message: | | ||
| # BENCHMARK FAILED | ||
|
|
||
| GPU Compression failed. Check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. | ||
| comment-tag: bench-pr-comment-gpu-compress | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,3 +14,14 @@ See [`src/main.rs`](./src/main.rs) for the dataset list and CLI flags (`--format | |
| ```bash | ||
| cargo run -p compress-bench --profile release_debug | ||
| ``` | ||
|
|
||
| GPU decompression is opt-in and runs only the existing benchmark names allow-listed in | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this GPU only then?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you mean? |
||
| `src/main.rs`: | ||
|
|
||
| ```bash | ||
| cargo run -p compress-bench --profile release_debug \ | ||
| --features cuda,unstable_encodings -- --gpu-decompress | ||
| ``` | ||
|
|
||
| On Linux, GPU files are read with direct IO (`O_DIRECT`) so repeated iterations measure | ||
| storage bandwidth rather than page-cache hits. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // SPDX-FileCopyrightText: Copyright the Vortex contributors | ||
|
|
||
| use std::hint::black_box; | ||
| use std::path::Path; | ||
| use std::sync::Arc; | ||
| use std::time::Duration; | ||
| use std::time::Instant; | ||
|
|
||
| use anyhow::Result; | ||
| use async_trait::async_trait; | ||
| use futures::StreamExt; | ||
| use tempfile::NamedTempFile; | ||
| use vortex::array::IntoArray; | ||
| use vortex::array::arrays::StructArray; | ||
| use vortex::array::arrays::struct_::StructArrayExt; | ||
| use vortex::compressor::BtrBlocksCompressorBuilder; | ||
| use vortex::file::OpenOptionsSessionExt; | ||
| use vortex::file::WriteOptionsSessionExt; | ||
| use vortex::file::WriteStrategyBuilder; | ||
| use vortex_bench::Format; | ||
| use vortex_bench::SESSION; | ||
| use vortex_bench::compress::Compressor; | ||
| use vortex_bench::conversions::parquet_to_vortex_chunks; | ||
| use vortex_cuda::CudaOpenOptionsExt; | ||
| use vortex_cuda::CudaSession; | ||
| #[cfg(target_os = "linux")] | ||
| use vortex_cuda::PooledFileReadAtOptions; | ||
| use vortex_cuda::executor::CudaArrayExt; | ||
| use vortex_cuda::layout::CudaFlatLayoutStrategy; | ||
| use vortex_cuda::layout::register_cuda_layout; | ||
|
|
||
| /// Vortex compressor whose decompression measurement executes CUDA-compatible files on the GPU. | ||
| pub struct GpuVortexCompressor; | ||
|
|
||
| #[async_trait] | ||
| impl Compressor for GpuVortexCompressor { | ||
| fn format(&self) -> Format { | ||
| Format::OnDiskVortex | ||
| } | ||
|
|
||
| async fn compress(&self, _parquet_path: &Path) -> Result<(u64, Duration)> { | ||
| anyhow::bail!("GPU compress-bench only supports decompression measurements") | ||
| } | ||
|
|
||
| async fn decompress(&self, parquet_path: &Path) -> Result<Duration> { | ||
| register_cuda_layout(&SESSION); | ||
|
|
||
| let uncompressed = parquet_to_vortex_chunks(parquet_path.to_path_buf()).await?; | ||
|
0ax1 marked this conversation as resolved.
|
||
| let gpu_file = NamedTempFile::new()?; | ||
| let mut output = tokio::fs::File::create(gpu_file.path()).await?; | ||
| let strategy = WriteStrategyBuilder::default() | ||
| .with_btrblocks_builder(BtrBlocksCompressorBuilder::default().only_cuda_compatible()) | ||
| .with_flat_strategy(Arc::new(CudaFlatLayoutStrategy::default())) | ||
| .build(); | ||
| SESSION | ||
| .write_options() | ||
| .with_strategy(strategy) | ||
| .write(&mut output, uncompressed.into_array().to_array_stream()) | ||
| .await?; | ||
| output.sync_all().await?; | ||
| drop(output); | ||
|
|
||
| let mut cuda_ctx = CudaSession::create_execution_ctx(&SESSION)?; | ||
| let start = Instant::now(); | ||
| let open_options = SESSION.open_options().with_cuda(); | ||
| // Direct IO keeps repeated iterations measuring storage bandwidth rather than | ||
| // page-cache hits. It is only available on Linux. | ||
| #[cfg(target_os = "linux")] | ||
| let open_options = | ||
| open_options.with_read_at_options(PooledFileReadAtOptions::default().with_direct_io()); | ||
| let file = open_options.open_path(gpu_file.path()).await?; | ||
| let mut batches = file.scan()?.into_array_stream()?; | ||
|
|
||
| while let Some(batch) = batches.next().await { | ||
| let record = batch?.execute::<StructArray>(cuda_ctx.execution_ctx())?; | ||
| for field in record.iter_unmasked_fields() { | ||
| black_box(field.clone().execute_cuda(&mut cuda_ctx).await?); | ||
| } | ||
| } | ||
| cuda_ctx.synchronize_stream()?; | ||
|
|
||
| Ok(start.elapsed()) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: probably this should be factored out and re-used across GPU CI tasks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ill create a follow up