Flux.jl: Batched Matrix Multiply

Created on 8 Jan 2019  路  2Comments  路  Source: FluxML/Flux.jl

It would be nice to able to use batched matrix multiples like those in BatchedRoutines.jl, ortorch.bmm since it seems roughly twice as fast.

A = rand(10,20,1000)
B = rand(20,10,1000)

function bmm(A,B)
    C = Array{eltype(A)}(undef,size(A,1),size(B,2),size(A,3))
    for i in 1:size(A,3)
        C[:,:,i] = A[:,:,i] * B[:,:,i]
    end
    C
end

@btime bmm(A,B) #   974.955 渭s (3002 allocations: 5.07 MiB)

@btime batched_gemm('N','N',A,B) #   433.808 渭s (2 allocations: 781.33 KiB)

However I can't seem to get it to work with a TrackedArray ?

Most helpful comment

Thanks for the help I got something working.

function bmm(A::TrackedArray, B::TrackedArray)
    track(bmm,A,B)
end

function bmm(A::Array,B::Array)
    batched_gemm('N','N',A,B)
end

function bmm(A::CuArray,B::CuArray)
    batched_gemm('N','N',A,B)
end

@grad function bmm(A,B)
     bmm(data(A),data(B)) ,螖 -> (batched_gemm('N' ,'T', 螖 , data(B)), batched_gemm( 'T' ,'N',data(A) , 螖))
end

All 2 comments

BatchedRoutines.jl ccalls in BLAS, LAPACK, etc for computing the results. So it will not work directly with TrackedArrays. But we can simply define the custom gradients (I dont know if we can handle this in any other way) to handle it. The process to describe custom gradients are here.

I had written a version for batched matrix multiplication for computing gram matrices. So it is essentially the batched version of x * x'. It can be adapted for A * B batched versions by just changing the gradient function.

gram_matrix_fast(x::TrackedArray) = track(gram_matrix_fast, x)

gram_matrix_fast(x::CuArray) = CuArrays.CUBLAS.gemm_strided_batched('T', 'N', x, x)

鈭噂ram_matrix_fast(x::CuArray, 螖::CuArray) =
    CuArrays.CUBLAS.gemm_strided_batched('N', 'N', x, 螖 .+ 螖') 

@grad function gram_matrix_fast(x)
    return gram_matrix_fast(data(x)), 螖 -> (鈭噂ram_matrix_fast(data(x), 螖), )
end

This was pretty much faster than simple multiplication (as your example). You can swap the functions from BatchedRoutines in place of the CUBLAS functions.

Thanks for the help I got something working.

function bmm(A::TrackedArray, B::TrackedArray)
    track(bmm,A,B)
end

function bmm(A::Array,B::Array)
    batched_gemm('N','N',A,B)
end

function bmm(A::CuArray,B::CuArray)
    batched_gemm('N','N',A,B)
end

@grad function bmm(A,B)
     bmm(data(A),data(B)) ,螖 -> (batched_gemm('N' ,'T', 螖 , data(B)), batched_gemm( 'T' ,'N',data(A) , 螖))
end
Was this page helpful?
0 / 5 - 0 ratings

Related issues

logankilpatrick picture logankilpatrick  路  6Comments

tejank10 picture tejank10  路  6Comments

caseykneale picture caseykneale  路  5Comments

aminya picture aminya  路  4Comments

jw3126 picture jw3126  路  6Comments