Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 22 additions & 57 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- 'release-'
tags: '*'
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
workflow_dispatch:

concurrency:
Expand All @@ -15,62 +16,26 @@ concurrency:

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
version:
- 'lts' # julia lts
- '1' # latest stable 1.x release of Julia
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
steps:
- uses: actions/checkout@v7
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v3
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-runtest@latest
env:
JULIA_NUM_THREADS: 4
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: lcov.info
name: "Tests"
uses: "QuantumKitHub/QuantumKitHubActions/.github/workflows/TestGroups.yml@main"
with:
fast: ${{ github.event.pull_request.draft == true }}
nthreads: 4
timeout-minutes: 90
# Enzyme plays a large role here, so also test macOS and Windows on PRs, once ubuntu passes
extra-os-on-prs: true
staged: ${{ github.event_name == 'pull_request' }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

test-nightly:
needs: test
name: Julia nightly - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
version:
- 'nightly'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
steps:
- uses: actions/checkout@v7
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v3
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-runtest@latest
continue-on-error: true
env:
JULIA_NUM_THREADS: 4
name: "Tests (nightly)"
uses: "QuantumKitHub/QuantumKitHubActions/.github/workflows/Tests.yml@main"
with:
julia-version: "nightly"
nthreads: 4
timeout-minutes: 90
coverage: false
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ LinearAlgebra = "1.6"
Logging = "1.6"
Mooncake = "0.5"
PackageExtensionCompat = "1"
ParallelTestRunner = "2"
PrecompileTools = "1.1"
Preferences = "1.4"
PtrArrays = "1.2"
Expand Down Expand Up @@ -86,10 +87,11 @@ EnzymeTestUtils = "12d8515a-0907-448a-8884-5fe00fdf1c5a"
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6"
ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TBLIS = "48530278-0828-4a49-9772-0f3830dfa1e9"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
cuTENSOR = "011b41b2-24ef-40a8-b3eb-fa098493e9e1"

[targets]
test = ["Test", "Random", "DynamicPolynomials", "ChainRulesTestUtils", "ChainRulesCore", "cuRAND", "CUDACore", "cuTENSOR", "Aqua", "Logging", "Bumper", "Mooncake", "Enzyme", "EnzymeTestUtils", "Adapt", "JLArrays", "AMDGPU", "TBLIS"]
test = ["Test", "Random", "DynamicPolynomials", "ChainRulesTestUtils", "ChainRulesCore", "cuRAND", "CUDACore", "cuTENSOR", "Aqua", "Logging", "Bumper", "Mooncake", "Enzyme", "EnzymeTestUtils", "Adapt", "JLArrays", "AMDGPU", "TBLIS", "ParallelTestRunner"]
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions test/core/aqua.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using TensorOperations
using Aqua
Aqua.test_all(TensorOperations)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion test/butensor.jl → test/extensions/bumper.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testset "@butensor dependency check" begin
@test_throws ArgumentError begin
ex = :(@butensor A[a, b, c, d] := B[a, b, c, d])
macroexpand(Main, ex)
macroexpand(@__MODULE__, ex)
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/cutensor.jl → test/extensions/cutensor.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testset "@cutensor dependency check" begin
@test_throws ArgumentError begin
ex = :(@cutensor A[a, b, c, d] := B[a, b, c, d])
macroexpand(Main, ex)
macroexpand(@__MODULE__, ex)
end
end

Expand Down
1 change: 1 addition & 0 deletions test/gpu.jl → test/extensions/gpuarrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ using TupleTools
using JLArrays
using VectorInterface
using CUDACore, AMDGPU
using cuTENSOR # contractions of `CuArray`s require the cuTENSOR extension

test_result(a::AbstractArray, b::AbstractArray; kwargs...) =
isapprox(collect(a), collect(b); kwargs...)
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions test/extensions/tblis_unsupported.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# the Windows build of `tblis_jll` aborts the process from inside the library, so
# the extension refuses to call into it and there is nothing else to test
using TensorOperations
using TBLIS
using Test

A = randn(Float64, (3, 4))
@test_throws ArgumentError tensoradd!(
zeros(Float64, (4, 3)), A, ((2, 1), ()), false, 1, 0,
TensorOperations.TBLISBackend()
)
149 changes: 54 additions & 95 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,109 +1,68 @@
using ParallelTestRunner
using TensorOperations
using LinearAlgebra
using Test
using Random
Random.seed!(1234567)

using TensorOperations: IndexError
using TensorOperations: BaseCopy, BaseView, StridedNative, StridedBLAS
using TensorOperations: DefaultAllocator, ManualAllocator, BufferAllocator
testsuite = find_tests(@__DIR__)

precision(::Type{<:Union{Float32, Complex{Float32}}}) = 1.0e-2
precision(::Type{<:Union{Float64, Complex{Float64}}}) = 1.0e-8
# --fast is passed by the CI on draft PRs, but there are no slow tests to skip
args = parse_args(ARGS; custom = ["fast"])
filter_tests!(testsuite, args)

# https://github.com/QuantumKitHub/TensorOperations.jl/issues/280: the generated code has to
# keep the user's `LineNumberNode`s -- Julia only emits a coverage counter for lines that a
# `LineNumberNode` points at -- and drop the ones synthesized by the parser, which would
# otherwise re-attribute the statements that follow them to a line in TensorOperations itself.
# Only `LineNumberNode`s in block-statement position matter for that: elsewhere (most notably
# the mandatory 2nd argument of a `:macrocall`) they are structurally required and left alone.
function statementlinenumbernodes(ex, acc = LineNumberNode[])
if ex isa Expr
if ex.head === :block
for e in ex.args
e isa LineNumberNode && push!(acc, e)
end
end
foreach(e -> statementlinenumbernodes(e, acc), ex.args)
end
return acc
# don't run all tests on GPU, only the GPU specific ones
if get(ENV, "BUILDKITE", "false") == "true"
filter!(in(("extensions/cutensor", "extensions/gpuarrays")) ∘ first, testsuite)
end
# the Windows build of TBLIS can only be tested for refusing to run
delete!(testsuite, Sys.iswindows() ? "extensions/tblis" : "extensions/tblis_unsupported")

# don't run all tests on GPU, only the GPU
# specific ones
is_buildkite = get(ENV, "BUILDKITE", "false") == "true"
if !is_buildkite
@testset "tensoropt" verbose = true begin
include("tensoropt.jl")
end
@testset "auxiliary" verbose = true begin
include("auxiliary.jl")
end
@testset "macro keywords" verbose = true begin
include("macro_kwargs.jl")
end
@testset "method syntax" verbose = true begin
include("methods.jl")
end
@testset "macro with index notation" verbose = true begin
include("tensor.jl")
end
@testset "allocator" verbose = true begin
include("allocator.jl")
end
@testset "ad" verbose = false begin
include("ad.jl")
end
@testset "mooncake" verbose = false begin
include("mooncake.jl")
end
is_apple_ci = Sys.isapple() && get(ENV, "CI", "false") == "true"
if !is_apple_ci
@testset "enzyme" verbose = false begin
include("enzyme.jl")
end
end
# The cuTENSOR and Bumper tests first check that the macros requiring them throw when they are
# not loaded, so they run on a fresh worker rather than one that may have loaded them already
const fresh_worker_tests = ("extensions/cutensor", "extensions/bumper")
const fresh_workers = Channel{ParallelTestRunner.PTRWorker}(Inf)
function test_worker(name)
name in fresh_worker_tests || return nothing
worker = addworker()
put!(fresh_workers, worker)
return worker
end

# note: cuTENSOR should not be loaded before this point
# as there is a test which requires it to be loaded after
@testset "cuTENSOR extension" verbose = true begin
include("cutensor.jl")
end
@testset "GPUArrays" verbose = true begin
include("gpu.jl")
end
const init_code = quote
using TensorOperations
using LinearAlgebra
using Test
using Random
Random.seed!(1234567)

if !is_buildkite
# note: Bumper should not be loaded before this point
# as there is a test which requires it to be loaded after
@testset "Bumper extension" verbose = true begin
include("butensor.jl")
end
const is_buildkite = get(ENV, "BUILDKITE", "false") == "true"

if Sys.iswindows()
# the Windows build of `tblis_jll` aborts the process from inside the library, so
# the extension refuses to call into it and there is nothing else to test
using TBLIS
@testset "TBLIS extension (unsupported platform)" begin
A = randn(Float64, (3, 4))
@test_throws ArgumentError tensoradd!(
zeros(Float64, (4, 3)), A, ((2, 1), ()), false, 1, 0,
TensorOperations.TBLISBackend()
)
end
else
@testset "TBLIS extension" verbose = true begin
include("tblis.jl")
end
end
using TensorOperations: IndexError
using TensorOperations: BaseCopy, BaseView, StridedNative, StridedBLAS
using TensorOperations: DefaultAllocator, ManualAllocator, BufferAllocator

@testset "Polynomials" begin
include("polynomials.jl")
end
precision(::Type{<:Union{Float32, Complex{Float32}}}) = 1.0e-2
precision(::Type{<:Union{Float64, Complex{Float64}}}) = 1.0e-8

@testset "Aqua" verbose = true begin
using Aqua
Aqua.test_all(TensorOperations)
# https://github.com/QuantumKitHub/TensorOperations.jl/issues/280: the generated code has to
# keep the user's `LineNumberNode`s -- Julia only emits a coverage counter for lines that a
# `LineNumberNode` points at -- and drop the ones synthesized by the parser, which would
# otherwise re-attribute the statements that follow them to a line in TensorOperations itself.
# Only `LineNumberNode`s in block-statement position matter for that: elsewhere (most notably
# the mandatory 2nd argument of a `:macrocall`) they are structurally required and left alone.
function statementlinenumbernodes(ex, acc = LineNumberNode[])
if ex isa Expr
if ex.head === :block
for e in ex.args
e isa LineNumberNode && push!(acc, e)
end
end
foreach(e -> statementlinenumbernodes(e, acc), ex.args)
end
return acc
end
end

try
runtests(TensorOperations, args; testsuite, init_code, test_worker)
finally
close(fresh_workers)
foreach(ParallelTestRunner.Malt.stop, fresh_workers)
end
Loading