# TensorCast & CUDA

**URL:** https://discourse.julialang.org/t/tensorcast-cuda/41483
**Category:** General Usage
**Tags:** question, cuda
**Created:** [June 15, 2020, 11:44pm UTC](https://discourse.julialang.org/t/tensorcast-cuda/41483 "2020-06-15T23:44:38Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![bryce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryce/32/15193_2.png) [@bryce](https://discourse.julialang.org/u/bryce)
#### Post date: [June 15, 2020, 11:44pm UTC](https://discourse.julialang.org/t/tensorcast-cuda/41483/1 "2020-06-15T23:44:38Z")

</div>

I’m having problems using TensorCast on CuArrays. When I run the following with normal arrays, it works fine:

```julia
using TensorCast
C = ones(10,2)
L = ones(10,3)
@reduce D[m,a] := sum(p) C[p,a] + L[p,m]

3×2 Array{Float64,2}:
 20.0 20.0
 20.0 20.0
 20.0 20.0

```

But if I do the same with CUDA arrays, it produces an error:

```julia
using TensorCast
using CUDA
CUDA.allowscalar(false)
C = cu(ones(10,2))
L = cu(ones(10,3))
@reduce D[m,a] := sum(p) C[p,a] + L[p,m]

ERROR: LoadError: scalar getindex is disallowed

```

It’s possible to do the CUDA version with @cast as an intermediate step as follows:

```julia
using TensorCast
using CUDA
CUDA.allowscalar(false)
C = cu(ones(10,2))
L = cu(ones(10,3))
@cast T[p,m,a] := C[p,a] + L[p,m]
D = reshape(sum(T, dims=1), (3,2))

3×2 CuArray{Float32,2,CuArray{Float32,3,Nothing}}:
 20.0 20.0
 20.0 20.0
 20.0 20.0

```

But it’s not at all clear to me why these would be different, so I have a few questions:

- Is there another way to do this operation with @reduce that I’m missing?
- Is there a performance difference between these (assuming they both worked)?
- Would the intermediate allocation of T be happening under-the-hood anyway?

---

<div class="post-metadata">

### Author: ![haberdashPI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haberdashpi/32/26337_2.png) [@haberdashPI](https://discourse.julialang.org/u/haberdashPI)
#### Post date: [June 16, 2020, 11:32am UTC](https://discourse.julialang.org/t/tensorcast-cuda/41483/2 "2020-06-16T11:32:39Z")

</div>

I _think_ the problem is that D is being initialized as an Array not a CuArray.

---

<div class="post-metadata">

### Author: ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)
#### Post date: [June 16, 2020, 12:16pm UTC](https://discourse.julialang.org/t/tensorcast-cuda/41483/3 "2020-06-16T12:16:35Z")

</div>

Here’s the expansion, the function `orient` is usually just `reshape` to put the dimensions along the `:`s.

```julia
julia> @pretty @reduce D[m,a] := sum(p) C[p,a] + L[p,m]
begin
    local dotterel = orient(PermuteDims(C), (*, :, :))
    local ant = orient(PermuteDims(L), (:, *, :))
    D = dropdims(sum(@ __dot__ (dotterel + ant), dims = 3), dims = 3)
end

```

Because reshaping a transposed `Array` usually gives something very slow, sometimes `orient` makes a copy, and perhaps it is incorrectly making a CPU array. I thought this was fixed in [https://github.com/mcabbott/TensorCast.jl/pull/10](https://github.com/mcabbott/TensorCast.jl/pull/10) but perhaps not. Do you mind making an issue?

Your work-around puts the index to be summed first instead of last, in which case there is no transposing required. The macro `@reduce` is unfortunately not smart enough to notice that possibility.

It will always make an intermediate allocation like `T`, broadcasting before reducing. There is an option `lazy` which uses LazyArrays.jl to avoid this allocation, but I’m not confident it has kept up with changes in that package, nor whether it will work with a CuArray.
