-
Notifications
You must be signed in to change notification settings - Fork 74
Initial wrap of hipTENSOR library #890
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
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
21c5269
Initial wrap of hipTENSOR library
67ab62d
Don't test hiptensor if it's not available
9c8cf04
Incremental wtf updates
7ec99ff
Fix the types
c6caad5
Fixes
fadf4bb
Get the hipTENSOR tests passing
a871e4e
Some code review fixes
7b14a0b
Check device architecture support for hipTENSOR
dc15da6
Update src/tensor/hipTENSOR.jl
kshyatt 4a0c4d5
Update src/utils.jl
kshyatt a8409d0
Get rid of unneeded import
c28a1cd
Add some docs
241c7de
Update src/utils.jl
kshyatt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Tensor Operations | ||
|
|
||
| `AMDGPU.jl` now provides wrappers for the [`hipTensor`](https://rocm.docs.amd.com/projects/hipTensor/en/latest/index.html) library, | ||
| which can be used to perform operations on high-dimensional arrays. However, there are some caveats: | ||
|
|
||
| - `hipTensor` isn't supported on every AMD GPU. You can find the list of supported GPUs [at the `hipTensor` documentation](https://rocm.docs.amd.com/projects/hipTensor/en/latest/api-reference/api-reference.html#supported-gpu-architectures). | ||
| - for [`hiptensorCreateElementwiseTrinary`](https://rocm.docs.amd.com/projects/hipTensor/en/latest/api-reference/api-reference.html#hiptensorcreateelementwisetrinary), `hipTENSOR` 2.2 has the two binary operators the wrong way round: it applies the | ||
| operator passed as `opABC` to `A` and `B`, and the one passed as `opAB` to that intermediate result and `C`. This is currently handled by our wrapper. | ||
| - Unlike NVIDIA's `cuTENSOR`, `hipTENSOR` wants a *complex* compute descriptor for complex operands: pairing e.g. `ComplexF32` tensors with `HIPTENSOR_COMPUTE_DESC_32F` makes | ||
| `hiptensorCreatePlan` fail with `HIPTENSOR_STATUS_EXECUTION_FAILED` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| using Clang.Generators | ||
| using JuliaFormatter | ||
|
|
||
| include_dir = normpath("/opt/rocm/include") | ||
| rocblas_dir = joinpath(include_dir, "hiptensor") | ||
| options = load_options("hiptensor/hiptensor-generator.toml") | ||
|
|
||
| args = get_default_args() | ||
| push!(args, "-I$include_dir") | ||
|
|
||
| headers = [ | ||
| joinpath(rocblas_dir, header) | ||
| for header in readdir(rocblas_dir) | ||
| if endswith(header, ".h") | ||
| ] | ||
|
|
||
| ctx = create_context(headers, args, options) | ||
| build!(ctx) | ||
|
|
||
| path = options["general"]["output_file_path"] | ||
| format_file(path, YASStyle()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| [general] | ||
| library_name = "libhiptensor" | ||
| output_file_path = "./libhiptensor.jl" | ||
| export_symbol_prefixes = [] | ||
| print_using_CEnum = false | ||
|
|
||
| [codegen] | ||
| use_ccall_macro = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| export hipTENSORError | ||
|
|
||
| struct hipTENSORError <: Exception | ||
| code::hiptensorStatus_t | ||
| end | ||
|
|
||
| Base.convert(::Type{hiptensorStatus_t}, err::hipTENSORError) = err.code | ||
|
|
||
| Base.showerror(io::IO, err::hipTENSORError) = | ||
| print(io, "hipTENSORError: ", description(err), " (code $(reinterpret(Int32, err.code)), $(name(err)))") | ||
|
|
||
| name(err::hipTENSORError) = unsafe_string(hiptensorGetErrorString(err)) | ||
|
|
||
| ## COV_EXCL_START | ||
| function description(err::hipTENSORError) | ||
| if err.code == HIPTENSOR_STATUS_SUCCESS | ||
| "the operation completed successfully" | ||
| elseif err.code == HIPTENSOR_STATUS_NOT_INITIALIZED | ||
| "the library was not initialized" | ||
| elseif err.code == HIPTENSOR_STATUS_ALLOC_FAILED | ||
| "the resource allocation failed" | ||
| elseif err.code == HIPTENSOR_STATUS_INVALID_VALUE | ||
| "an invalid value was used as an argument" | ||
| elseif err.code == HIPTENSOR_STATUS_ARCH_MISMATCH | ||
| "an absent device architectural feature is required" | ||
| elseif err.code == HIPTENSOR_STATUS_EXECUTION_FAILED | ||
| "the GPU program failed to execute" | ||
| elseif err.code == HIPTENSOR_STATUS_INTERNAL_ERROR | ||
| "an internal operation failed" | ||
| elseif err.code == HIPTENSOR_STATUS_NOT_SUPPORTED | ||
| "operation not supported (yet)" | ||
| elseif err.code == HIPTENSOR_STATUS_CK_ERROR | ||
| "error detected trying to check the license" | ||
| elseif err.code == HIPTENSOR_STATUS_HIP_ERROR | ||
| "error occurred during a HIP operation" | ||
| elseif err.code == HIPTENSOR_STATUS_INSUFFICIENT_WORKSPACE | ||
| "insufficient workspace memory for this operation" | ||
| elseif err.code == HIPTENSOR_STATUS_INSUFFICIENT_DRIVER | ||
| "insufficient driver version" | ||
| elseif err.code == HIPTENSOR_STATUS_IO_ERROR | ||
| "file not found" | ||
| else | ||
| "no description for this error" | ||
| end | ||
| end | ||
| ## COV_EXCL_STOP |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| module hipTENSOR | ||
|
|
||
| using AMDGPU | ||
| using GPUToolbox: @gcsafe_ccall, @checked, @enum_without_prefix, @debug_ccall | ||
| using AMDGPU: Mem | ||
|
|
||
| using BFloat16s: BFloat16 | ||
| import AMDGPU: libhiptensor, HandleCache, HIP, library_state | ||
| import AMDGPU.Mem: alloc_or_retry! | ||
| import .HIP: HIPContext, HIPStream, hipStream_t | ||
|
|
||
| using CEnum: @cenum | ||
|
|
||
| using Printf: @printf | ||
|
|
||
| export has_hiptensor | ||
|
|
||
| has_hiptensor() = AMDGPU.functional(:hiptensor) | ||
|
|
||
| # core library | ||
| include("libhiptensor.jl") | ||
|
|
||
| # low-level wrappers | ||
| include("error.jl") | ||
| include("types.jl") | ||
| include("operations.jl") | ||
|
|
||
| # high-level integrations | ||
| include("interfaces.jl") | ||
|
|
||
|
|
||
| ## handles | ||
|
|
||
| function create_handle() | ||
| AMDGPU.functional(:hiptensor) || error("hipTENSOR is not available") | ||
|
|
||
| handle_ref = Ref{hiptensorHandle_t}() | ||
| hiptensorCreate(handle_ref) | ||
| handle_ref[] | ||
| end | ||
|
|
||
| const IDLE_HANDLES = HandleCache{HIPContext,hiptensorHandle_t}() | ||
|
|
||
| lib_state() = library_state( | ||
| :hipTENSOR, hiptensorHandle_t, IDLE_HANDLES, | ||
| create_handle, hiptensorDestroy, (handle, stream) -> 0 ) | ||
|
|
||
| handle() = lib_state().handle | ||
| stream() = lib_state().stream | ||
|
|
||
| function version() | ||
| ver = hiptensorGetVersion() | ||
| major = ver ÷ 10000 | ||
| minor = (ver ÷ 100) % 100 | ||
| patch = ver % 100 | ||
| return VersionNumber(join((major,minor,patch), ".")) | ||
| end | ||
|
|
||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # interfacing with other packages | ||
|
|
||
| ## Base | ||
|
|
||
| function Base.:(+)(A::hipTensor, B::hipTensor) | ||
| α = convert(eltype(A), 1.0) | ||
| γ = convert(eltype(B), 1.0) | ||
| C = similar(B) | ||
| elementwise_binary_execute!(α, A.data, A.inds, HIPTENSOR_OP_IDENTITY, | ||
| γ, B.data, B.inds, HIPTENSOR_OP_IDENTITY, | ||
| C.data, C.inds, HIPTENSOR_OP_ADD) | ||
| return C | ||
| end | ||
|
|
||
| function Base.:(-)(A::hipTensor, B::hipTensor) | ||
| α = convert(eltype(A), 1.0) | ||
| γ = convert(eltype(B), -1.0) | ||
| C = similar(B) | ||
| elementwise_binary_execute!(α, A.data, A.inds, HIPTENSOR_OP_IDENTITY, | ||
| γ, B.data, B.inds, HIPTENSOR_OP_IDENTITY, | ||
| C.data, C.inds, HIPTENSOR_OP_ADD) | ||
| return C | ||
| end | ||
|
|
||
| function Base.:(*)(A::hipTensor, B::hipTensor) | ||
| tC = promote_type(eltype(A), eltype(B)) | ||
| A_uniqs = [(idx, i) for (idx, i) in enumerate(A.inds) if !(i in B.inds)] | ||
| B_uniqs = [(idx, i) for (idx, i) in enumerate(B.inds) if !(i in A.inds)] | ||
| A_sizes = map(x->size(A,x[1]), A_uniqs) | ||
| B_sizes = map(x->size(B,x[1]), B_uniqs) | ||
| A_inds = map(x->x[2], A_uniqs) | ||
| B_inds = map(x->x[2], B_uniqs) | ||
| C = hipTensor(fill!(similar(B.data, tC, Dims(vcat(A_sizes, B_sizes))), zero(tC)), vcat(A_inds, B_inds)) | ||
| return mul!(C, A, B) | ||
| end | ||
|
|
||
|
|
||
| ## LinearAlgebra | ||
|
|
||
| using LinearAlgebra | ||
|
|
||
| function LinearAlgebra.axpy!(a, X::hipTensor, Y::hipTensor) | ||
| elementwise_binary_execute!(a, X.data, X.inds, HIPTENSOR_OP_IDENTITY, | ||
| one(eltype(Y)), Y.data, Y.inds, HIPTENSOR_OP_IDENTITY, | ||
| Y.data, Y.inds, HIPTENSOR_OP_ADD) | ||
| return Y | ||
| end | ||
|
|
||
| function LinearAlgebra.axpby!(a, X::hipTensor, b, Y::hipTensor) | ||
| elementwise_binary_execute!(a, X.data, X.inds, HIPTENSOR_OP_IDENTITY, | ||
| b, Y.data, Y.inds, HIPTENSOR_OP_IDENTITY, | ||
| Y.data, Y.inds, HIPTENSOR_OP_ADD) | ||
| return Y | ||
| end | ||
|
|
||
| function LinearAlgebra.mul!(C::hipTensor, A::hipTensor, B::hipTensor, α::Number, β::Number) | ||
| contract!(α, A.data, A.inds, HIPTENSOR_OP_IDENTITY, | ||
| B.data, B.inds, HIPTENSOR_OP_IDENTITY, β, | ||
| C.data, C.inds, HIPTENSOR_OP_IDENTITY, HIPTENSOR_OP_IDENTITY; | ||
| jit=HIPTENSOR_JIT_MODE_DEFAULT) | ||
| return C | ||
| end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.