Broadcasting on views

Hello,

I would like to perform a broadcast operation on views with indices stored in a struct. I am not sure how exactly to acheive this with Julia syntax.

Essentially I have a struct like so:

struct Foo
     id::Integer
     work::AbstractArray
end

where work contains a list of indices, and a vector of type Foo, bar = [Foo(1, [1,2]), Foo(2, [3,4])].

I would like to perform a broadcasting dot operation for example, but with indices from bar. So essentially, I would like to iterate through the array of Foo and create views for two vecs using the indices work.

out = broadcast(dot, view(vec1, ?bar.work), view(vec2, ?bar.work))

I know I can do this with a for loop:

out = zeros(Float, size(Bar))
idx=1
for i in eachindex(bar)
    out[idx] = dot(view(vec1, i.work), view(vec2, i.work)) 
    idx++
end

but I think this would be more efficient and scalable with a broadcast, as for me the indices are guaranteed to be indepedent.

broadcast is not more efficient than a (properly) handwritten loop in Julia. Loops in Julia are fast.

I’m a little confused by your code, because your example loop doesn’t seem functional (e.g. what is i.work where i is an index?). But if I understand you correctly, you want something like:

out = dot.(view.(Ref(vec1), getproperty.(bar, :work)),
           view.(Ref(vec2), getproperty.(bar, :work)))

though honestly it seems cleaner to me to use a comprehension:

@views out = [dot(vec1[foo.work], vec2[foo.work]) for foo in bar]
1 Like

The i.work was a misunderstanding on my part of Julia syntax (I assumed that i was of type Foo rather than just an index). But it seems like you are right. Atleast for this problem, a regular for loop (with pre-allocation) seems to be the way to go.

If I wrap that into a function, then I think it should be acceptable for me. Thanks for your help!