Skip to content

Commit 8d29d61

Browse files
committed
Fix find_first_set_bit_kernel kernel compute error
1 parent 093d87e commit 8d29d61

4 files changed

Lines changed: 323 additions & 9 deletions

File tree

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
on:
2+
workflow_call:
3+
inputs:
4+
build_type:
5+
description: "One of: [branch, nightly, pull-request]"
6+
required: true
7+
type: string
8+
matrix_type:
9+
description: "One of: [auto, nightly, pull-request]. 'auto' means 'choose a value based on what's provided via build_type'."
10+
required: false
11+
type: string
12+
default: "auto"
13+
branch:
14+
description: |
15+
Git branch the workflow run targets.
16+
This is required even when 'sha' is provided because it is also used for organizing artifacts.
17+
type: string
18+
date:
19+
description: "Date (YYYY-MM-DD) this run is for. Used to organize artifacts produced by nightly builds"
20+
type: string
21+
sha:
22+
description: "Full git commit SHA to check out"
23+
type: string
24+
repo:
25+
description: "Git repo to check out, in '{org}/{repo}' form, e.g. 'rapidsai/cudf'"
26+
type: string
27+
script:
28+
type: string
29+
required: true
30+
description: "Shell code to be executed in a step. Ideally this should just invoke a script managed in the repo the workflow runs from, like 'ci/test_cpp.sh'."
31+
matrix_filter:
32+
description: |
33+
jq expression which modifies the matrix.
34+
For example, 'map(select(.ARCH == "amd64"))' to achieve "only run amd64 jobs".
35+
type: string
36+
default: "."
37+
container-options:
38+
description: |
39+
Command-line arguments passed to 'docker run' when starting the container this workflow runs in.
40+
This should be provided as a single string to be inlined into 'docker run', not an array.
41+
For example, '--quiet --ulimit nofile=2048'.
42+
required: false
43+
type: string
44+
default: "-e _NOOP"
45+
build_workflow_name:
46+
description: |
47+
Name of a workflow file that produced artifacts to be downloaded in this run.
48+
If not set (the default), artifact-handling scripts use RAPIDS-conventional defaults (like "build.yaml" when "build_type == nightly").
49+
required: false
50+
type: string
51+
sccache-dist-request-timeout:
52+
type: string
53+
default: 7140
54+
description: |
55+
The maximum time (in seconds) the sccache client should wait for a distributed compilation to complete.
56+
sccache-dist-token-secret-name:
57+
type: string
58+
required: false
59+
description: |
60+
The name of the secret that contains the token used to authenticate with the RAPIDS Build Engineering sccache-dist build cluster.
61+
alternative-gh-token-secret-name:
62+
type: string
63+
required: false
64+
description: |
65+
If provided, should contain the name of a secret in the repo which holds a GitHub API token.
66+
When this is non-empty, that secret's value is used in place of the default repo-level token
67+
anywhere that environment variable GH_TOKEN is set. This is especially useful for downloading
68+
artifacts from other private repos, which repo tokens do not have access to.
69+
secrets:
70+
script-env-secret-1-key:
71+
description: |
72+
Name of an environment variable in the environment where 'inputs.script' is run.
73+
Variable's value will be set to the value passed as 'secrets.script-env-secret-1-value'.
74+
required: false
75+
script-env-secret-1-value:
76+
description: |
77+
Secret value.
78+
Will be available via an environment variable named by 'secrets.script-env-secret-1-key'.
79+
required: false
80+
script-env-secret-2-key:
81+
description: |
82+
Name of an environment variable in the environment where 'inputs.script' is run.
83+
Variable's value will be set to the value passed as 'secrets.script-env-secret-2-value'.
84+
required: false
85+
script-env-secret-2-value:
86+
description: |
87+
Secret value.
88+
Will be available via an environment variable named by 'secrets.script-env-secret-2-key'.
89+
required: false
90+
script-env-secret-3-key:
91+
description: |
92+
Name of an environment variable in the environment where 'inputs.script' is run.
93+
Variable's value will be set to the value passed as 'secrets.script-env-secret-3-value'.
94+
required: false
95+
script-env-secret-3-value:
96+
description: |
97+
Secret value.
98+
Will be available via an environment variable named by 'secrets.script-env-secret-3-key'.
99+
required: false
100+
101+
defaults:
102+
run:
103+
shell: bash
104+
105+
permissions:
106+
actions: read
107+
checks: none
108+
contents: read
109+
deployments: none
110+
discussions: none
111+
id-token: write
112+
issues: none
113+
packages: read
114+
pages: none
115+
pull-requests: read
116+
repository-projects: none
117+
security-events: none
118+
statuses: none
119+
120+
jobs:
121+
compute-matrix:
122+
runs-on: ubuntu-latest
123+
env:
124+
BUILD_TYPE: ${{ inputs.build_type }}
125+
MATRIX_TYPE: ${{ inputs.matrix_type }}
126+
outputs:
127+
MATRIX: ${{ steps.compute-matrix.outputs.MATRIX }}
128+
steps:
129+
- name: Validate Inputs
130+
run: |
131+
if [[ "$BUILD_TYPE" != "branch" ]] && [[ "$BUILD_TYPE" != "nightly" ]] && [[ "$BUILD_TYPE" != "pull-request" ]]; then
132+
echo "Invalid build_type! Must be one of 'branch', 'nightly', or 'pull-request'."
133+
exit 1
134+
fi
135+
if [[ "$MATRIX_TYPE" != "auto" ]] && [[ "$MATRIX_TYPE" != "nightly" ]] && [[ "$MATRIX_TYPE" != "pull-request" ]]; then
136+
echo "Invalid matrix_type! Must be one of 'auto', 'nightly', or 'pull-request'."
137+
exit 1
138+
fi
139+
- name: Compute C++ Test Matrix
140+
id: compute-matrix
141+
env:
142+
MATRIX_FILTER: ${{ inputs.matrix_filter }}
143+
run: |
144+
set -eo pipefail
145+
146+
# please keep the matrices sorted in ascending order by the following:
147+
#
148+
# [ARCH, PY_VER, CUDA_VER, LINUX_VER, GPU, DRIVER, DEPENDENCIES]
149+
#
150+
export MATRICES="
151+
nightly:
152+
# amd64
153+
- { ARCH: 'amd64', PY_VER: '3.11', CUDA_VER: '12.2.2', LINUX_VER: 'rockylinux8', GPU: 'l4', DRIVER: 'earliest', DEPENDENCIES: 'oldest' }
154+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '12.9.1', LINUX_VER: 'ubuntu24.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
155+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LINUX_VER: 'ubuntu24.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
156+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.1.0', LINUX_VER: 'ubuntu24.04', GPU: 'h100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
157+
# arm64
158+
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '12.2.2', LINUX_VER: 'ubuntu22.04', GPU: 'a100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
159+
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.0.2', LINUX_VER: 'ubuntu22.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
160+
- { ARCH: 'arm64', PY_VER: '3.13', CUDA_VER: '13.1.0', LINUX_VER: 'ubuntu22.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
161+
pull-request:
162+
# amd64
163+
- { ARCH: 'amd64', PY_VER: '3.11', CUDA_VER: '12.2.2', LINUX_VER: 'rockylinux8', GPU: 'l4', DRIVER: 'earliest', DEPENDENCIES: 'oldest' }
164+
- { ARCH: 'amd64', PY_VER: '3.11', CUDA_VER: '12.2.2', LINUX_VER: 'ubuntu22.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
165+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LINUX_VER: 'rockylinux8', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
166+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '12.2.2', LINUX_VER: 'rockylinux8', GPU: 'v100', DRIVER: 'earliest', DEPENDENCIES: 'latest' }
167+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '12.9.1', LINUX_VER: 'ubuntu24.04', GPU: 'h100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
168+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.1.0', LINUX_VER: 'ubuntu24.04', GPU: 'h100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
169+
# arm64
170+
- { ARCH: 'arm64', PY_VER: '3.11', CUDA_VER: '12.2.2', LINUX_VER: 'ubuntu22.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'oldest' }
171+
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '12.9.1', LINUX_VER: 'ubuntu22.04', GPU: 'l4', DRIVER: 'latest', DEPENDENCIES: 'latest' }
172+
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.0.2', LINUX_VER: 'rockylinux8', GPU: 'a100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
173+
- { ARCH: 'arm64', PY_VER: '3.13', CUDA_VER: '13.1.0', LINUX_VER: 'rockylinux8', GPU: 'a100', DRIVER: 'latest', DEPENDENCIES: 'latest' }
174+
"
175+
176+
# only overwrite MATRIX_TYPE if it was set to 'auto'
177+
if [[ "${MATRIX_TYPE}" == "auto" ]]; then
178+
if [[ "${BUILD_TYPE}" == "branch" ]]; then
179+
# Use the nightly matrix for branch tests
180+
MATRIX_TYPE="nightly"
181+
else
182+
MATRIX_TYPE="${BUILD_TYPE}"
183+
fi
184+
fi
185+
export MATRIX_TYPE
186+
TEST_MATRIX=$(yq -n 'env(MATRICES) | .[strenv(MATRIX_TYPE)]')
187+
export TEST_MATRIX
188+
189+
MATRIX="$(
190+
yq -n -o json 'env(TEST_MATRIX)' | \
191+
jq -c "${MATRIX_FILTER} | if (. | length) > 0 then {include: .} else \"Error: Empty matrix\n\" | halt_error(1) end"
192+
)"
193+
194+
echo "MATRIX=${MATRIX}" | tee --append "${GITHUB_OUTPUT}"
195+
tests:
196+
name: ${{ matrix.CUDA_VER }}, ${{ matrix.PY_VER }}, ${{ matrix.ARCH }}, ${{ matrix.LINUX_VER }}, ${{ matrix.GPU }}, ${{ matrix.DRIVER }}-driver, ${{ matrix.DEPENDENCIES }}-deps
197+
needs: compute-matrix
198+
strategy:
199+
fail-fast: false
200+
matrix: ${{ fromJSON(needs.compute-matrix.outputs.MATRIX) }}
201+
runs-on: "linux-${{ matrix.ARCH }}-gpu-${{ matrix.GPU }}-${{ matrix.DRIVER }}-1"
202+
env:
203+
RAPIDS_ARTIFACTS_DIR: ${{ github.workspace }}/artifacts
204+
RAPIDS_DEPENDENCIES: ${{ matrix.DEPENDENCIES }}
205+
RAPIDS_TESTS_DIR: ${{ github.workspace }}/test-results
206+
container:
207+
image: rapidsai/ci-conda:26.04-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}
208+
options: ${{ inputs.container-options }}
209+
env:
210+
RAPIDS_BUILD_TYPE: ${{ inputs.build_type }}
211+
NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }}
212+
steps:
213+
- uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
214+
with:
215+
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
216+
aws-region: ${{ vars.AWS_REGION }}
217+
role-duration-seconds: 43200 # 12h
218+
219+
- uses: actions/checkout@v6
220+
with:
221+
repository: ${{ inputs.repo }}
222+
ref: ${{ inputs.sha }}
223+
fetch-depth: 0
224+
persist-credentials: true
225+
# This has to be AFTER the checkout step. It creates a telemetry-artifacts directory,
226+
# and the checkout step would destroy it.
227+
- name: Telemetry setup
228+
uses: rapidsai/shared-actions/telemetry-dispatch-setup@main
229+
continue-on-error: true
230+
if: ${{ vars.TELEMETRY_ENABLED == 'true' }}
231+
with:
232+
extra_attributes: "rapids.PACKAGER=conda,rapids.CUDA_VER=${{ matrix.CUDA_VER }},rapids.PY_VER=${{ matrix.PY_VER }},rapids.ARCH=${{ matrix.ARCH }},rapids.LINUX_VER=${{ matrix.LINUX_VER }},rapids.GPU=${{ matrix.GPU }},rapids.DRIVER=${{ matrix.DRIVER }},rapids.DEPENDENCIES=${{ matrix.DEPENDENCIES }}"
233+
env:
234+
# DOES NOT NEED alternative-gh-token-secret_name - github.token is enough and more limited
235+
GH_TOKEN: ${{ github.token }}
236+
237+
- name: Standardize repository information
238+
uses: rapidsai/shared-actions/rapids-github-info@main
239+
with:
240+
repo: ${{ inputs.repo }}
241+
branch: ${{ inputs.branch }}
242+
date: ${{ inputs.date }}
243+
sha: ${{ inputs.sha }}
244+
build_workflow_name: ${{ inputs.build_workflow_name }}
245+
246+
- name: Setup proxy cache
247+
uses: nv-gha-runners/setup-proxy-cache@main
248+
continue-on-error: true
249+
250+
# Install latest rapidsai/sccache client and configure sccache-dist
251+
- name: Setup sccache-dist
252+
uses: rapidsai/shared-actions/setup-sccache-dist@main
253+
if: ${{ inputs.sccache-dist-token-secret-name != '' }}
254+
env:
255+
AWS_REGION: "${{env.AWS_REGION}}"
256+
AWS_ACCESS_KEY_ID: "${{env.AWS_ACCESS_KEY_ID}}"
257+
AWS_SECRET_ACCESS_KEY: "${{env.AWS_SECRET_ACCESS_KEY}}"
258+
with:
259+
auth: "${{ secrets[inputs.sccache-dist-token-secret-name] }}" # zizmor: ignore[overprovisioned-secrets]
260+
log-file: "${{ env.RAPIDS_ARTIFACTS_DIR }}/sccache.log"
261+
request-timeout: ${{ inputs.sccache-dist-request-timeout }}
262+
# Per the docs at https://docs.github.com/en/rest/rate-limit/rate-limit?apiVersion=2022-11-28#get-rate-limit-status-for-the-authenticated-user,
263+
# checking '/rate_limit | jq .' should not itself count against any rate limits.
264+
#
265+
# gh CLI is pre-installed on Github-hosted runners, but may not be on self-hosted runners.
266+
- name: Check GitHub API rate limits
267+
run: |
268+
if ! type gh >/dev/null; then
269+
echo "'gh' CLI is not installed... skipping rate-limits check"
270+
else
271+
gh api /rate_limit | jq .
272+
fi
273+
env:
274+
# NEEDS alternative-gh-token-secret_name - API limits need to be for whatever token is used for upload/download. Repo token may be a different pool for rate limits.
275+
GH_TOKEN: ${{ inputs.alternative-gh-token-secret-name && secrets[inputs.alternative-gh-token-secret-name] || github.token }} # zizmor: ignore[overprovisioned-secrets]
276+
# cannot put possibly-null things as keys in the 'env:' mapping, so need to process these in a script
277+
- name: Set secrets in script env
278+
run: |
279+
set_env_var() {
280+
local input_prefix="script-env-secret-$1"
281+
local key_str=$2
282+
local val_str=$3
283+
if test -n "${val_str}"; then
284+
if ! test -n "${key_str}"; then
285+
echo "ERROR: '${input_prefix}-value' non-empty but '${input_prefix}-key' is empty. Set '${input_prefix}-key'."
286+
exit 1
287+
fi
288+
echo "${key_str}=${val_str}" >> "${GITHUB_ENV}"
289+
fi
290+
}
291+
set_env_var '1' '${{ secrets.script-env-secret-1-key }}' '${{ secrets.script-env-secret-1-value }}'
292+
set_env_var '2' '${{ secrets.script-env-secret-2-key }}' '${{ secrets.script-env-secret-2-value }}'
293+
set_env_var '3' '${{ secrets.script-env-secret-3-key }}' '${{ secrets.script-env-secret-3-value }}'
294+
- name: C++ tests
295+
run: |
296+
ulimit -n "$(ulimit -Hn)"
297+
$INPUTS_SCRIPT
298+
env:
299+
INPUTS_SCRIPT: "${{ inputs.script }}"
300+
SCCACHE_DIST_TOKEN_NAME: "${{ inputs.sccache-dist-token-secret-name }}"
301+
# NEEDS alternative-gh-token-secret-name - may require a token with more permissions
302+
GH_TOKEN: ${{ inputs.alternative-gh-token-secret-name && secrets[inputs.alternative-gh-token-secret-name] || github.token }} # zizmor: ignore[overprovisioned-secrets]
303+
- name: Generate test report
304+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4
305+
with:
306+
paths: "${{ env.RAPIDS_TESTS_DIR }}/*.xml"
307+
if: always()
308+
- name: Upload additional artifacts
309+
if: "!cancelled()"
310+
run: rapids-upload-artifacts-dir "cuda${RAPIDS_CUDA_VERSION%%.*}_$(arch)"
311+
- name: Telemetry upload attributes
312+
uses: rapidsai/shared-actions/telemetry-dispatch-stash-job-artifacts@main
313+
continue-on-error: true
314+
if: ${{ vars.TELEMETRY_ENABLED == 'true' }}
315+
env:
316+
# DOES NOT NEED alternative-gh-token-secret-name - github.token is enough and more limited
317+
GH_TOKEN: ${{ github.token }}

‎.github/workflows/pr.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ jobs:
234234
conda-cpp-tests:
235235
needs: [conda-cpp-build, changed-files]
236236
secrets: inherit
237-
uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-tests.yaml@main
237+
uses: rapidsai/cudf/.github/workflows/conda-cpp-tests.yaml@fix-first-bit-error
238238
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp
239239
with:
240240
build_type: pull-request

‎cpp/src/bitmask/null_mask.cu‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -743,15 +743,10 @@ CUDF_KERNEL void find_first_set_bit_kernel(bitmask_type const* __restrict__ bitm
743743
auto const block = cg::tiled_partition<block_size>(cg::this_thread_block());
744744
auto const tid = cudf::detail::grid_1d::global_thread_id<block_size>();
745745

746-
cuda::atomic_ref<size_type, cuda::thread_scope_device> ref{*(index)};
747-
if (ref.load(cuda::std::memory_order_relaxed) != max) {
748-
return; // early exit if bit has already been found
749-
}
750-
751-
auto const end_word_index = word_index(stop);
752-
753746
auto const thread_word_index = tid + word_index(start);
754-
auto bit_index = max;
747+
auto const end_word_index = word_index(stop);
748+
749+
auto bit_index = max;
755750
if (thread_word_index <= end_word_index) {
756751
auto const mask = detail::get_mask_offset_word(bitmask, tid, start, stop);
757752
// returned index is 1-based; 0 means no bits were set
@@ -764,6 +759,7 @@ CUDF_KERNEL void find_first_set_bit_kernel(bitmask_type const* __restrict__ bitm
764759
block.sync();
765760

766761
if (block.thread_rank() == 0 && out_index != max) {
762+
cuda::atomic_ref<size_type, cuda::thread_scope_device> ref{*(index)};
767763
ref.fetch_min(out_index, cuda::std::memory_order_relaxed);
768764
}
769765
}

‎cpp/tests/bitmask/bitmask_tests.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ TEST_F(CountBitmaskTest, IndexOfFirstUnsetBit)
395395
for (auto parm : parameters) {
396396
auto data = std::vector<bool>(parm.size, false);
397397
data[parm.set_index] = true;
398+
std::fill(data.begin() + parm.set_index + 1, data.end(), (parm.set_index >= parm.start_index));
398399
auto input =
399400
cudf::test::fixed_width_column_wrapper<int, bool>(data.begin(), data.end(), data.begin())
400401
.release();

0 commit comments

Comments
 (0)