{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "e271b0e0-8e90-4e73-83a1-25c94fa8a9e6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "@atime (macro with 1 method)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using BenchmarkTools\n", "macro atime(expr) :(@btime $expr samples=1 evals=1) end" ] }, { "cell_type": "code", "execution_count": 2, "id": "061f4513-203e-4298-915a-996fa0010281", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MethodInstance for PermutedDimsArray(::Array{Int64, 4}, ::NTuple{4, Int64})\n", " from PermutedDimsArray(data::AbstractArray{T, N}, perm) where {T, N} in Base.PermutedDimsArrays at permuteddimsarray.jl:42\n", "Static Parameters\n", " T = \u001b[36mInt64\u001b[39m\n", " N = \u001b[36m4\u001b[39m\n", "Arguments\n", " #self#\u001b[36m::Type{PermutedDimsArray}\u001b[39m\n", " data\u001b[36m::Array{Int64, 4}\u001b[39m\n", " perm\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "Locals\n", " iperm\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "Body\u001b[91m\u001b[1m::PermutedDimsArray{Int64, 4, _A, _B, Array{Int64, 4}} where {_A, _B}\u001b[22m\u001b[39m\n", "\u001b[90m1 ─\u001b[39m Core.NewvarNode(:(iperm))\n", "\u001b[90m│ \u001b[39m %2 = Base.PermutedDimsArrays.length(perm)\u001b[36m::Core.Const(4)\u001b[39m\n", "\u001b[90m│ \u001b[39m %3 = (%2 == $(Expr(:static_parameter, 2)))\u001b[36m::Core.Const(true)\u001b[39m\n", "\u001b[90m│ \u001b[39m Core.typeassert(%3, Core.Bool)\n", "\u001b[90m└──\u001b[39m goto #3\n", "\u001b[90m2 ─\u001b[39m Core.Const(:(Base.PermutedDimsArrays.string(perm, \" is not a valid permutation of dimensions 1:\", $(Expr(:static_parameter, 2)))))\n", "\u001b[90m│ \u001b[39m Core.Const(:(Base.PermutedDimsArrays.ArgumentError(%6)))\n", "\u001b[90m└──\u001b[39m Core.Const(:(Base.PermutedDimsArrays.throw(%7)))\n", "\u001b[90m3 ┄\u001b[39m (iperm = Base.PermutedDimsArrays.invperm(perm))\n", "\u001b[90m│ \u001b[39m %10 = $(Expr(:static_parameter, 1))\u001b[36m::Core.Const(Int64)\u001b[39m\n", "\u001b[90m│ \u001b[39m %11 = $(Expr(:static_parameter, 2))\u001b[36m::Core.Const(4)\u001b[39m\n", "\u001b[90m│ \u001b[39m %12 = Core._apply_iterate(Base.iterate, Core.tuple, perm)\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "\u001b[90m│ \u001b[39m %13 = Core._apply_iterate(Base.iterate, Core.tuple, iperm)\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "\u001b[90m│ \u001b[39m %14 = Base.PermutedDimsArrays.typeof(data)\u001b[36m::Core.Const(Array{Int64, 4})\u001b[39m\n", "\u001b[90m│ \u001b[39m %15 = Core.apply_type(Base.PermutedDimsArrays.PermutedDimsArray, %10, %11, %12, %13, %14)\u001b[91m\u001b[1m::Type{PermutedDimsArray{Int64, 4, _A, _B, Array{Int64, 4}}} where {_A, _B}\u001b[22m\u001b[39m\n", "\u001b[90m│ \u001b[39m %16 = (%15)(data)\u001b[91m\u001b[1m::PermutedDimsArray{Int64, 4, _A, _B, Array{Int64, 4}} where {_A, _B}\u001b[22m\u001b[39m\n", "\u001b[90m└──\u001b[39m return %16\n", "\n" ] } ], "source": [ "A = rand(0:9, 2, 3, 4, 5)\n", "perm = (4, 3, 1, 2)\n", "@code_warntype PermutedDimsArray(A, perm)" ] }, { "cell_type": "code", "execution_count": 3, "id": "8aef944c-1d6d-4bd2-bae5-55457063ad00", "metadata": {}, "outputs": [ { "data": { "text/html": [ "PermutedDimsArray(data::AbstractArray{T, N}, perm) where {T, N} in Base.PermutedDimsArrays at permuteddimsarray.jl:42" ], "text/plain": [ "PermutedDimsArray(data::AbstractArray{T, N}, perm) where {T, N} in Base.PermutedDimsArrays at permuteddimsarray.jl:42" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@which PermutedDimsArray(zeros(1, 2, 3, 4), (4, 2, 1, 3))" ] }, { "cell_type": "code", "execution_count": 4, "id": "9477f6e5-2156-495f-9461-d251101df637", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Main.O" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "module O\n", "\n", "struct PermutedDimsArray{T,N,AA<:AbstractArray{T,N},NT<:Dims{N}} <: AbstractArray{T,N}\n", " parent::AA\n", " perm::NT\n", " iperm::NT\n", "end\n", "\n", "function PermutedDimsArray(data::AbstractArray{T,N}, perm::Dims{N}) where {T,N}\n", " iperm = invperm(perm)\n", " PermutedDimsArray{T,N,typeof(data),typeof(perm)}(data, perm, iperm)\n", "end\n", "function PermutedDimsArray(data::AbstractArray{T,N}, perm) where {T,N}\n", " PermutedDimsArray(data, Dims{N}(perm))\n", "end\n", "\n", "Base.parent(A::PermutedDimsArray) = A.parent\n", "Base.size(A::PermutedDimsArray{T,N}) where {T,N} = genperm(size(parent(A)), A.perm)\n", "Base.axes(A::PermutedDimsArray{T,N}) where {T,N} = genperm(axes(parent(A)), A.perm)\n", "\n", "Base.similar(A::PermutedDimsArray, T::Type, dims::Base.Dims) = similar(parent(A), T, dims)\n", "\n", "Base.unsafe_convert(::Type{Ptr{T}}, A::PermutedDimsArray{T}) where {T} = Base.unsafe_convert(Ptr{T}, parent(A))\n", "\n", "Base.pointer(A::PermutedDimsArray, i::Integer) = throw(ArgumentError(\"pointer(A, i) is deliberately unsupported for PermutedDimsArray\"))\n", "\n", "function Base.strides(A::PermutedDimsArray{T,N}) where {T,N}\n", " s = strides(parent(A))\n", " ntuple(d->s[A.perm[d]], Val(N))\n", "end\n", "Base.elsize(::Type{<:PermutedDimsArray{<:Any, <:Any, P}}) where {P} = Base.elsize(P)\n", "\n", "@inline function Base.getindex(A::PermutedDimsArray{T,N}, I::Vararg{Int,N}) where {T,N}\n", " @boundscheck checkbounds(A, I...)\n", " @inbounds val = getindex(A.parent, genperm(I, A.iperm)...)\n", " val\n", "end\n", "@inline function Base.setindex!(A::PermutedDimsArray{T,N}, val, I::Vararg{Int,N}) where {T,N}\n", " @boundscheck checkbounds(A, I...)\n", " @inbounds setindex!(A.parent, val, genperm(I, A.iperm)...)\n", " val\n", "end\n", "\n", "@inline genperm(I::NTuple{N,Any}, perm::Dims{N}) where {N} = ntuple(d -> I[perm[d]], Val(N))\n", "@inline genperm(I, perm::AbstractVector{Int}) = genperm(I, (perm...,))\n", "\n", "end" ] }, { "cell_type": "code", "execution_count": 5, "id": "93665a6d-82d2-44fe-8de3-35cf45ce7d71", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MethodInstance for Main.O.PermutedDimsArray(::Array{Int64, 4}, ::NTuple{4, Int64})\n", " from Main.O.PermutedDimsArray(data::AbstractArray{T, N}, perm::Tuple{Vararg{Int64, N}}) where {T, N} in Main.O at In[4]:9\n", "Static Parameters\n", " T = \u001b[36mInt64\u001b[39m\n", " N = \u001b[36m4\u001b[39m\n", "Arguments\n", " #self#\u001b[36m::Type{Main.O.PermutedDimsArray}\u001b[39m\n", " data\u001b[36m::Array{Int64, 4}\u001b[39m\n", " perm\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "Locals\n", " iperm\u001b[36m::NTuple{4, Int64}\u001b[39m\n", "Body\u001b[36m::Main.O.PermutedDimsArray{Int64, 4, Array{Int64, 4}, NTuple{4, Int64}}\u001b[39m\n", "\u001b[90m1 ─\u001b[39m (iperm = Main.O.invperm(perm))\n", "\u001b[90m│ \u001b[39m %2 = $(Expr(:static_parameter, 1))\u001b[36m::Core.Const(Int64)\u001b[39m\n", "\u001b[90m│ \u001b[39m %3 = $(Expr(:static_parameter, 2))\u001b[36m::Core.Const(4)\u001b[39m\n", "\u001b[90m│ \u001b[39m %4 = Main.O.typeof(data)\u001b[36m::Core.Const(Array{Int64, 4})\u001b[39m\n", "\u001b[90m│ \u001b[39m %5 = Main.O.typeof(perm)\u001b[36m::Core.Const(NTuple{4, Int64})\u001b[39m\n", "\u001b[90m│ \u001b[39m %6 = Core.apply_type(Main.O.PermutedDimsArray, %2, %3, %4, %5)\u001b[36m::Core.Const(Main.O.PermutedDimsArray{Int64, 4, Array{Int64, 4}, NTuple{4, Int64}})\u001b[39m\n", "\u001b[90m│ \u001b[39m %7 = (%6)(data, perm, iperm)\u001b[36m::Main.O.PermutedDimsArray{Int64, 4, Array{Int64, 4}, NTuple{4, Int64}}\u001b[39m\n", "\u001b[90m└──\u001b[39m return %7\n", "\n" ] } ], "source": [ "A = rand(0:9, 2, 3, 4, 5)\n", "perm = (4, 3, 1, 2)\n", "@code_warntype O.PermutedDimsArray(A, perm)" ] }, { "cell_type": "code", "execution_count": 6, "id": "b5f4a05d-8bb5-4d3a-a129-76041475a5eb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 5.900 μs (4 allocations: 176 bytes)\n", " 200.000 ns (0 allocations: 0 bytes)\n" ] }, { "data": { "text/plain": [ "true" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = rand(2, 3, 4, 5)\n", "perm = (4, 3, 1, 2)\n", "B = @atime PermutedDimsArray($A, $perm)\n", "C = @atime O.PermutedDimsArray($A, $perm)\n", "B == C" ] }, { "cell_type": "code", "execution_count": 7, "id": "c4ffaeec-04a9-41dd-8d5c-87d2eff38e47", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 8.500 μs (5 allocations: 272 bytes)\n", " 300.000 ns (0 allocations: 0 bytes)\n" ] }, { "data": { "text/plain": [ "true" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = rand(2, 3, 4, 5)\n", "perm = [4, 3, 1, 2]\n", "B = @atime PermutedDimsArray($A, $perm)\n", "C = @atime O.PermutedDimsArray($A, $perm)\n", "B == C" ] }, { "cell_type": "code", "execution_count": null, "id": "6c2b0903-b140-4a1e-832f-54d2cc8be86b", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "jupytext": { "formats": "ipynb,jl:hydrogen" }, "kernelspec": { "display_name": "Julia 1.8.0", "language": "julia", "name": "julia-1.8" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.8.0" } }, "nbformat": 4, "nbformat_minor": 5 }