Skip to content

BLAS/LAPACK calls need numeric traits #154

Open
@timholy

Description

@timholy

If I wrap a numeric type, I can't use BLAS or LAPACK calls anymore. This hurts performance considerably:

module Elements

export MyEl

immutable MyEl{T}
    el::T
end

Base.zero{T}(::Type{MyEl{T}}) = MyEl{T}(zero(T))
Base.conj!{T<:Real}(A::Array{MyEl{T}}) = A
Base.promote_rule{T,S}(::Type{MyEl{T}}, ::Type{MyEl{S}}) = MyEl{promote_type{T,S}}
+{S,T}(a::MyEl{S}, b::MyEl{T}) = MyEl{promote_type(S,T)}(a.el+b.el)
*{S,T}(a::MyEl{S}, b::MyEl{T}) = MyEl{promote_type(S,T)}(a.el*b.el)

end

julia> using Elements

julia> A = rand(200,199);

julia> B = reinterpret(MyEl{Float64}, A);

# After warmup
julia> @time A'*A;
elapsed time: 0.002651306 seconds (316976 bytes allocated)

julia> @time B'*B;
elapsed time: 0.020106977 seconds (317216 bytes allocated)

It's using the generic_matmatmul! fallback, since a MyEl{Float64} is not recognized as a type that one can pass to BLAS/LAPACK.

It would seem that the best approach would be to define a set of numeric traits and have the BLAS/LAPACK routines use them. I'm submitting this issue to open discussion about how best to do this. Here's one proposal:

blastype{T}(::Type{T}) = T
blastype{T}(::Type{MyEl{T}}) = T  # defined by package author

some_blas_call(A::StridedArray) = some_blas_call(blastype(eltype(A)), A)
function some_blas_call{T<:BlasComplex}(::Type{T}, A)
    # the version that calls blas goes here
end
function some_blas_call{T}(::Type{T}, A)
    # the generic fallback goes here
end

[cjh: colorized]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions