Sparse-checkout from NVIDIA/cccl main branch to complete cccl_upstream: Added: - python/cuda_cccl/ (226 files) — Python bindings for device-level algorithms Critical for muh toolchain: cuda.compute.reduce_into, scan, radix_sort, etc. Includes 204 .py files with full test coverage for all 27 algorithms - ci/ (163 files) — Build/test infrastructure build_cub.sh, test_cub.sh, build_and_test_targets.sh, matrix.yaml Directly maps to our [INFRA-CI] and [INFRA-BUILD] items - .agent/skills/ (7 files) — NVIDIA's own agent skills for CCCL cccl-style/SKILL.md, cccl-test/SKILL.md, sass-diff/SKILL.md - docs/ (491 files) — Official CCCL documentation CI references, CMake guides, Python compute docs, libcudacxx PTX docs - test/ (12 files) — Top-level integration tests (cuda_smoke, stdpar) - Root configs: .clang-format, .clang-tidy, CONTRIBUTING.md, pyproject.toml - CLAUDE.md symlink → AGENTS.md (NVIDIA's standard) cccl_upstream now mirrors full NVIDIA/cccl structure: Before: 42M (cub + thrust + libcudacxx + cudax + c + examples + benchmarks) After: 53M (+python +ci +docs +.agent +test +configs) This completes the CCCL base needed for: - [muh-bench] items: ci/util/build_and_test_targets.sh for targeted builds - [CCCL-verify] items: python/cuda_cccl/tests/ as reference implementations - [CCCL-test] items: ci/test_cub.sh, ci/test_thrust.sh - Agent workflow: .agent/skills/ for consistent style and test patterns
247 lines
7.9 KiB
PowerShell
247 lines
7.9 KiB
PowerShell
function Get-Python {
|
|
<#
|
|
.SYNOPSIS
|
|
Returns the path of the Python interpreter satisfying the supplied
|
|
version, installing it via uv if necessary.
|
|
.PARAMETER Version
|
|
A string in the form 'M.m' (e.g., '3.10', '3.13') or a free-threaded
|
|
version such as '3.14t'.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory, Position = 0)]
|
|
[ValidatePattern('^\d+\.\d+t?$')]
|
|
[string]$Version
|
|
)
|
|
|
|
# Install uv if not present. uv downloads pre-built CPython binaries --
|
|
# no compilation, no build dependencies, no pyenv-win required.
|
|
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
|
Write-Host "Installing uv..."
|
|
Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression
|
|
# uv installs to $HOME\.local\bin on Windows
|
|
$uvBin = Join-Path $HOME '.local\bin'
|
|
$Env:PATH = $uvBin + ";" + $Env:PATH
|
|
}
|
|
|
|
Write-Host "Creating Python $Version venv via uv..."
|
|
$venvDir = Join-Path $HOME '.cccl-venv'
|
|
& uv venv --seed --python $Version $venvDir
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw [System.InvalidOperationException]::new(
|
|
"Failed to create Python $Version venv via uv."
|
|
)
|
|
}
|
|
|
|
$exe = Join-Path $venvDir 'Scripts\python.exe'
|
|
if (-not (Test-Path $exe)) {
|
|
throw [System.InvalidOperationException]::new(
|
|
"Could not find python.exe in venv at $exe"
|
|
)
|
|
}
|
|
|
|
Write-Host "Python $Version at: $exe"
|
|
|
|
# Add venv Scripts dir to PATH so bare `python` and `pip` work.
|
|
$scriptsDir = Join-Path $venvDir 'Scripts'
|
|
$Env:PATH = $scriptsDir + ";" + $Env:PATH
|
|
|
|
return $exe
|
|
}
|
|
|
|
function Get-RepoRoot {
|
|
return (Resolve-Path "$PSScriptRoot/../..")
|
|
}
|
|
|
|
function Get-CudaMajor {
|
|
<#
|
|
.SYNOPSIS
|
|
Gets the CUDA major version for this container instance (e.g. '12' or
|
|
'13'). Defaults to '13' if no match can be found.
|
|
#>
|
|
if ($env:CUDA_PATH) {
|
|
$nvcc = Join-Path $env:CUDA_PATH "bin/nvcc.exe"
|
|
if (Test-Path $nvcc) {
|
|
$out = & $nvcc --version 2>&1
|
|
$text = ($out -join "`n")
|
|
if ($text -match 'release\s+(\d+)\.') { return $Matches[1] }
|
|
}
|
|
# Fallback: parse major from CUDA_PATH like ...\v13.0 or ...\CUDA\13
|
|
$pathMatch = [regex]::Match($env:CUDA_PATH, 'v?(\d+)(?:\.\d+)?')
|
|
if ($pathMatch.Success) { return $pathMatch.Groups[1].Value }
|
|
}
|
|
return '13'
|
|
}
|
|
|
|
function Get-CudaVersion {
|
|
<#
|
|
.SYNOPSIS
|
|
Gets the CUDA major.minor version for this container instance (e.g.
|
|
'12.9' or '13.0'). Defaults to '13.0' if no match can be found.
|
|
#>
|
|
if ($env:CUDA_PATH) {
|
|
$nvcc = Join-Path $env:CUDA_PATH "bin/nvcc.exe"
|
|
if (Test-Path $nvcc) {
|
|
$out = & $nvcc --version 2>&1
|
|
$text = ($out -join "`n")
|
|
if ($text -match 'release\s+(\d+\.\d+)') { return $Matches[1] }
|
|
}
|
|
# Fallback: parse major.minor from CUDA_PATH like ...\v13.0
|
|
$pathMatch = [regex]::Match($env:CUDA_PATH, 'v?(\d+\.\d+)')
|
|
if ($pathMatch.Success) { return $pathMatch.Groups[1].Value }
|
|
}
|
|
return '13.0'
|
|
}
|
|
|
|
function Get-CtkTestMode {
|
|
<#
|
|
.SYNOPSIS
|
|
Validates and normalizes a CTK test mode passed as -Mode (forwarded from
|
|
the -ctk-mode arg): 'pinned' (default; empty means pinned), 'latest', or
|
|
'sysctk'. Throws on any other value (fail loud on a typo'd mode). Returns
|
|
the lowercased mode.
|
|
#>
|
|
param([string]$Mode = "")
|
|
if ([string]::IsNullOrEmpty($Mode)) { return "pinned" }
|
|
$Mode = $Mode.ToLowerInvariant()
|
|
if (-not ($Mode -in @("pinned", "latest", "sysctk"))) {
|
|
throw "Invalid ctk mode '$Mode' (expected pinned|latest|sysctk)"
|
|
}
|
|
return $Mode
|
|
}
|
|
|
|
function Set-CtkPin {
|
|
<#
|
|
.SYNOPSIS
|
|
Configures cuda-toolkit pinning for this lane per the -Mode arg (see
|
|
Get-CtkTestMode): 'pinned' (default) pins cuda-toolkit to the container's
|
|
CTK major.minor via PIP_CONSTRAINT; 'latest' and 'sysctk' leave it
|
|
unpinned ('sysctk' installs no cuda-toolkit wheel at all -- the
|
|
system-provided toolkit is used).
|
|
#>
|
|
param([string]$Mode = "")
|
|
if ((Get-CtkTestMode $Mode) -eq "pinned") {
|
|
$cudaVersion = Get-CudaVersion
|
|
$env:PIP_CONSTRAINT = Join-Path ([System.IO.Path]::GetTempPath()) "ctk-constraint.txt"
|
|
"cuda-toolkit==$cudaVersion.*" | Out-File -FilePath $env:PIP_CONSTRAINT -Encoding ascii
|
|
} else {
|
|
# latest / sysctk: no pin. Clear any inherited constraint so it cannot
|
|
# affect the resolve.
|
|
Remove-Item Env:\PIP_CONSTRAINT -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
function Get-CtkExtraFlavor {
|
|
<#
|
|
.SYNOPSIS
|
|
Returns the pip-extra toolkit "flavor" for the given -Mode: 'sysctk' when
|
|
the mode is sysctk (rely on the system-provided CUDA toolkit) or 'cu'
|
|
otherwise (pip-installed toolkit). Combine with the CUDA major, e.g.
|
|
"minimal-$(Get-CtkExtraFlavor $CtkMode)$cudaMajor".
|
|
#>
|
|
param([string]$Mode = "")
|
|
if ((Get-CtkTestMode $Mode) -eq "sysctk") { return "sysctk" }
|
|
return "cu"
|
|
}
|
|
|
|
function Convert-ToUnixPath {
|
|
Param([Parameter(Mandatory = $true)][string]$p)
|
|
return ($p -replace "\\", "/")
|
|
}
|
|
|
|
function Get-CudaCcclWheel {
|
|
<#
|
|
.SYNOPSIS
|
|
Returns the path of the cuda-cccl wheel artifact to use in the context
|
|
of a GitHub Actions CI test script.
|
|
#>
|
|
Param()
|
|
|
|
$repoRoot = Get-RepoRoot
|
|
if ($env:GITHUB_ACTIONS) {
|
|
Push-Location $repoRoot
|
|
try {
|
|
$wheelArtifactName = (& bash -lc "ci/util/workflow/get_wheel_artifact_name.sh").Trim()
|
|
if (-not $wheelArtifactName) { throw 'Failed to resolve wheel artifact name' }
|
|
$repoRootPosix = Convert-ToUnixPath $repoRoot
|
|
# Ensure output from downloader goes to console, not function return pipeline
|
|
$null = (& bash -lc "ci/util/artifacts/download.sh $wheelArtifactName $repoRootPosix" 2>&1 | Out-Host)
|
|
if ($LASTEXITCODE -ne 0) { throw "Failed to download wheel artifact '$wheelArtifactName'" }
|
|
}
|
|
finally { Pop-Location }
|
|
}
|
|
|
|
$wheelhouse = Join-Path $repoRoot 'wheelhouse'
|
|
$wheelPath = Get-OnePathMatch -Path $wheelhouse -Pattern '^cuda_cccl-.*\.whl' -File
|
|
return $wheelPath
|
|
}
|
|
|
|
function Get-OnePathMatch {
|
|
<#
|
|
.SYNOPSIS
|
|
Returns a single path (file or directory) match for a given pattern,
|
|
throwing an error if there were no matches or more than one match.
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName = 'FileSet')]
|
|
param(
|
|
[Parameter(Mandatory)]
|
|
[string] $Path,
|
|
|
|
[Parameter(Mandatory)]
|
|
[string] $Pattern,
|
|
|
|
[Parameter(Mandatory, ParameterSetName = 'FileSet')]
|
|
[switch] $File,
|
|
|
|
[Parameter(Mandatory, ParameterSetName = 'DirSet')]
|
|
[switch] $Directory,
|
|
|
|
[switch] $Recurse
|
|
)
|
|
|
|
if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
|
|
throw "Path not found or not a directory: $Path"
|
|
}
|
|
|
|
$gciArgs = @{
|
|
LiteralPath = $Path
|
|
ErrorAction = 'SilentlyContinue'
|
|
}
|
|
|
|
if ($Recurse) { $gciArgs['Recurse'] = $true }
|
|
if ($PSCmdlet.ParameterSetName -eq 'FileSet') {
|
|
$gciArgs['File'] = $true
|
|
}
|
|
else {
|
|
$gciArgs['Directory'] = $true
|
|
}
|
|
|
|
$pathMatches = @(
|
|
Get-ChildItem @gciArgs |
|
|
Where-Object { $_.Name -match $Pattern } |
|
|
Select-Object -ExpandProperty FullName
|
|
)
|
|
|
|
if ($pathMatches.Count -ne 1) {
|
|
$kind = if ($PSCmdlet.ParameterSetName -eq 'FileSet') { 'file' }
|
|
else { 'directory' }
|
|
$indented = ($pathMatches | ForEach-Object { " $_" }) -join "`n"
|
|
|
|
$msg = @"
|
|
Expected exactly one $kind name matching regex:
|
|
$Pattern
|
|
under:
|
|
$Path
|
|
Found:
|
|
$($pathMatches.Count)
|
|
|
|
$indented
|
|
"@
|
|
throw $msg
|
|
}
|
|
|
|
return $pathMatches[0]
|
|
}
|
|
|
|
Export-ModuleMember -Function Get-Python, Get-CudaMajor, Set-CtkPin, Get-CtkExtraFlavor, Convert-ToUnixPath, Get-RepoRoot, Get-CudaCcclWheel, Get-OnePathMatch
|