# Using argument vectors along specific dimensions during broadcast()

**URL:** <https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337>\
**Category:** General Usage\
**Created:** [August 29, 2023, 4:20pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337 "2023-08-29T16:20:50Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [August 29, 2023, 4:20pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337/1 "2023-08-29T16:20:50Z")

</div>

I’m wondering if there is a way to use vector arguments along specific dimensions during `broadcast()`.

For example, consider a function `f(x,y,z)` takeing three arguments corresponding to the 3D Cartesian coordinates. I have the x-, y-, z-coordinates as three separate vectors: `xs::Vector{Float64}`, `ys::Vector{Float64}`, `zs::Vector{Float64}`. I would like to broadcast `f()` over the 3D grid defined by `xs`, `ys`, `zs`. This can be achieved by

```julia
Nx, Ny, Nz = length(xs), length(ys), length(zs)
xs2 = reshape(xs, (Nx, 1, 1))
ys2 = reshape(ys, (1, Ny, 1))
zs2 = reshape(zs, (1, 1, Nz))

F = broadcast(f, xs2, ys2, zs2)

```

but `reshape()` is allocating. So, I’m wondering if there is a way to achieve the above without `reshape()`, probably something like

```julia
F = broadcast(f, xs, ys, zs, dims=(1,2,3))

```

where `dims` specify the dimension along which the three arguments need to be aligned.

Or, is there a way to turn a vector into an arbitrary dimensional linear array without allocation? I tried something like `permutedims()`, but it didn’t work.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 29, 2023, 4:42pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337/2 "2023-08-29T16:42:10Z")

</div>

> [@wsshin](#):
>
> but `reshape()` is allocating.

`reshape` should not allocate.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 29, 2023, 4:50pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337/3 "2023-08-29T16:50:16Z")

</div>

It does a small amount for builtin `Array`s (it’s just for the array header, not copying the data). You unfortunately need to explicitly opt-in to the pure-Julia reshape with `ReshapedArray`. (cf [#36313](https://github.com/JuliaLang/julia/issues/36313)).

Instead of broadcasting, I’d use `Iterators.product` here:

```julia
F = [f(x,y,z) for (x,y,z) in Iterators.product(xs, ys, zs)]

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [August 29, 2023, 5:03pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337/4 "2023-08-29T17:03:23Z")

</div>

Perhaps

```julia
using Tullio
@tullio F[i,j,k] := f(x[i], y[j], z[k])

```

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [August 29, 2023, 6:29pm UTC](https://discourse.julialang.org/t/using-argument-vectors-along-specific-dimensions-during-broadcast/103337/5 "2023-08-29T18:29:11Z")

</div>

@mbauman and @hendri54, thanks for the cool tricks. Actually I’m doing on GPU as well, and both methods use scalar indexing, which is slow on GPU. For example, with a setup

```julia
using CUDA
CUDA.allowscalar(false)
xs = cu(rand(10)); ys = cu(rand(20)); zs = cu(rand(30));
f(x,y,z) = x+y+z

```

I get

```julia-repl
julia> F = [f(x,y,z) for (x,y,z) in Iterators.product(xs, ys, zs)]
ERROR: Scalar indexing is disallowed.
...

```

and

```julia-repl
julia> using Tullio

julia> F = cu(rand(10,20,30));

julia> @tullio F[i,j,k] := f(xs[i], ys[j], zs[k])
ERROR: Scalar indexing is disallowed.

```

Wondering if there is a GPU-friendly workaround.
