# What is the future of \`sin(::Vector)\` when there is \`sin.(::Vector)\`?

**URL:** https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677
**Category:** Internals & Design
**Created:** [December 1, 2016, 5:28pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677 "2016-12-01T17:28:56Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)
#### Post date: [December 1, 2016, 5:28pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/1 "2016-12-01T17:28:56Z")

</div>

Since - as I understand it - the new broadcast sugar is the new way of computing the element-wise value of a function I wonder what the plan is with the special vectorized versions, such as `sin(::Vector)` for example. Is the plan that they will continue to work as is or are there thoughts about repurposing the signature?

I am asking because I contemplate how to go about this with LossFunctions.jl and I do try to keep things “julian”. Personally, at least for my use-case, I am considering making the special old version return a generator expression (in the lines of `(sin(x[i]) for i in eachindex(x))` to go with the sinus example), which would allow me in my use-case to do `mean(sin(x))`, which for loss functions would be quite nice. So maybe my second question, if you grand me this little digression, is that something that would be considered un-julian?

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [December 1, 2016, 5:36pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/2 "2016-12-01T17:36:01Z")

</div>

All vectorized functions like `sin(::Vector)` are going to be deprecated, except for very specific cases. You can write `mean(sin(x) for x in X)` to avoid allocating a new vector.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 1, 2016, 5:43pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/3 "2016-12-01T17:43:57Z")

</div>

> [@nalimilan](#):
>
> All vectorized functions like sin(::Vector) are going to be deprecated, except for very specific cases.

Those specific cases being the cases where it’s faster to have a specific method for vector computations (aren’t special functions able to be computed faster in vectorized forms using SIMD and other tricks? Will these tricks be added to Amal.jl and be part of the standard math library?)? Will there be a good documented way to know what the exceptions will be?

Wow, that ended up being a lot of questions that’s a bit more general than the title.

---

<div class="post-metadata">

### Author: ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)
#### Post date: [December 1, 2016, 6:01pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/4 "2016-12-01T18:01:01Z")

</div>

I can work with that. Thanks.

If people aren’t expecting the function without `.` to be vectorized then I have a simpler time repurposing the signature (for the functions of the package, that is). Well, the one paramater `sin` example isn’t the best example for my use-case I admit. For my use-case it would be `mean(loss(y,yhat) for (y,yhat) in zip(Y, Yhat))` or something like that, which is a handful and a bit much to expect a user to bother with.

Edit: I am not quite sure how to “accept” your answer or I would do so.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [December 1, 2016, 6:23pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/5 "2016-12-01T18:23:09Z")

</div>

> [@nalimilan](#):
>
> All vectorized functions like sin(::Vector) are going to be deprecated, except for very specific cases.

See also [Deprecate functions vectorized via `@vectorize_(1|2)arg` in favor of compact broadcast syntax by Sacha0 · Pull Request #17302 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/17302) and subsequent PRs cited in this one.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 3:49am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/6 "2016-12-05T03:49:47Z")

</div>

> [@ChrisRackauckas](#):
>
> Those specific cases being the cases where it’s faster to have a specific method for vector computations?

I hope not: `sin([1,2,3])` makes no sense from the Taylor series definition, regardless of if there’s a fast way to broadcast.

If there’s a faster specific broadcast, then one could overload

```julia
function broadcast(f::typeof(sin),x::Vector)
# do fast broadcast
end

```

so that `sin.([1,2,3])` is automatically fast.

---

<div class="post-metadata">

### Author: ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)
#### Post date: [December 5, 2016, 4:01am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/7 "2016-12-05T04:01:51Z")

</div>

Unfortunately, you have to be careful in overloading `broadcast` based on functions since dot-call fusion will result in any number of complex signatures and the unknown type of some anonymous function created by the parser… so you need to be sure your optimized method produces identical output to before you defined it (e.g. including that the outputted storage container can’t depend on the function in any robust way) and be aware the your optimization will only be used in a vanilla call to `broadcast`.

I’d love to see a more modular system, but I have no way of going about it.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 4:08am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/8 "2016-12-05T04:08:39Z")

</div>

I don’t think you’d want the optimization used in fused broadcasts to avoid allocation, so the desired behaviour is that `exp.(sin.([1,2,3]))` would revert to the default broadcast behaviour.

If a user is expected to be aware that `sin([1,2,3])` exists and is faster than `sin.([1,2,3])`, then they’d be capable of unfusing a call if desired: `exp.((sin.([1,2,3])))` would use the fast broadcast. (Assuming here that fusing doesn’t dig through parentheses.)

---

<div class="post-metadata">

### Author: ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)
#### Post date: [December 5, 2016, 4:24am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/9 "2016-12-05T04:24:26Z")

</div>

> I don’t think you’d want the optimization used in fused broadcasts to avoid allocation

Probably true in any practical case.

I think I’ve taken a slight tangent here: what I am saying is that broadcast _can_ dispatch on a function, but usually shouldn’t (or should only in a restricted set of circumstances). However, the logic of broadcast depends only on the storage contains inputted (and the return type of the function). `Base` has internal functions like `broadcast_c` (“broadcast container”) and so-on to perform this logic but I’m still working my way through it to see if I can find ways to hook into this system more neatly than _StaticArrays.jl_ and _Switches.jl_ currently do. Something modular and well-documented (like the promotion system & `promote_rule`) here would be fantastic!

To the topic - it would be even better if the modular system specified how to specialize your (scalar) function to run faster over collections of inputs (e.g. could become stateful to eliminate redundant computations, or have some SIMD friendly signature, or whatever). EDIT: a good system would compose correctly such that SIMD friendliness is maintained even if automatic fusion occurs.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 4:32am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/10 "2016-12-05T04:32:03Z")

</div>

OK, I don’t know enough about `broadcast` overloading to comment.

My primary point is that `f([1,2,3])` should only be implemented when it makes sense for the function in question. So the ‘except for very specific cases’ should not include something like `exp([1,2,3])` as the following makes no sense:

\sum\_{k=0}^\infty {[1,2,3]^k \over k!}

and is the reasonable definition for `exp` (well, not counting Cauchy integral formulas).

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 5, 2016, 4:59am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/11 "2016-12-05T04:59:46Z")

</div>

> [@andyferris](#):
>
> To the topic - it would be even better if the modular system specified how to specialize your (scalar) function to run faster over collections of inputs (e.g. could become stateful to eliminate redundant computations, or have some SIMD friendly signature, or whatever). EDIT: a good system would compose correctly such that SIMD friendliness is maintained even if automatic fusion occurs.

What about if a pre-allocated version exists, then it won’t fuse?

```julia
sin!(out,[1 3 5])

```

The reason I’m thinking about this is because things like GPU libraries will definitely want to use functions on vectors, and a pre-allocated version probably works in any of these cases?

---

<div class="post-metadata">

### Author: ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)
#### Post date: [December 5, 2016, 5:42am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/12 "2016-12-05T05:42:20Z")

</div>

> [@andyferris](#):
>
> To the topic - it would be even better if the modular system specified how to specialize your (scalar) function to run faster over collections of inputs (e.g. could become stateful to eliminate redundant computations, or have some SIMD friendly signature, or whatever). EDIT: a good system would compose correctly such that SIMD friendliness is maintained even if automatic fusion occurs.

FWIW, I suspect this line of thinking is eventually going to lead to the conclusion that many optimizations are not possible unless your full vector-level computation is represented as a plan for a computation that you can optimize as a whole since you need to exploit the way in which functions interact for maximum performance.

Building such a system would be an amazing win for Julia, but I feel like the simplicity of how `broadcast` works now is a virtue for functionality that goes in Base since it’s reasonable for a good programmer to learn how `broadcast` works in full detail.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 5:54am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/13 "2016-12-05T05:54:51Z")

</div>

> [@ChrisRackauckas](#):
>
> What about if a pre-allocated version exists, then it won’t fuse?
> 
> sin!(out,[1 3 5])
> 
> The reason I’m thinking about this is because things like GPU libraries will definitely want to use functions on vectors, and a pre-allocated version probably works in any of these cases?

Isn’t `sin!(out,[1 3 5])` equivalent to

```julia
out .= sin.([1 3 4])

```

It seems like with the right overrides this syntax would translate to GPU arrays.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 5, 2016, 6:09am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/14 "2016-12-05T06:09:13Z")

</div>

> [@dlfivefifty](#):
>
> It seems like with the right overrides this syntax would translate to GPU arrays.

Yes, that’s the issue though. As pointed out, your solution of:

```julia
function broadcast(f::typeof(sin),x::Vector)
# do fast broadcast
end

```

doesn’t necessarily work because, if I understand correctly, when broadcasts are fused like in `y .= sin.(x) + cos.(x)`, the `f` that is called is an anonymous function `f = (x)->sin(x)+cos(x)` and so writing an override for `out .= sin.([1 3 4])` doesn’t easily generalize to cases where broadcast fusing will take place.

Here’s a way of looking at it. When you don’t have optimized vector forms, on the scalar form what you’d want to do is:

```julia
f = (x) -> sin(x) + cos(x)
y .= f.(x)

```

But you can also avoid temporaries by using non-allocating `sin!` and `cos!`, and then add them. (But this gets difficult because you need a cache). So in the case where you want to use optimized vector functions, you’d want to do something like:

```julia
sin!(cache1,x)
cos!(cache2,x)
y.= cache1 .+ cache2

```

Somehow we want something like `y .= sin.(x) + cos.(x)` to mean both of these, depending on whether a “fast vectorized form” exists. I am not sure that this could be done automatically (since how else could caches be specified?), so I am suggesting that

```julia
y .= sin!(cache1,x) .+ cos!(cache2,x)

```

would have to be the way to go. The RNG already do something like this so there’s precedent. So I would suggest that, since any optimized vector form is for performance, the only form that should really need to be present is the mutating version. It would be easy to document too because it would be a different function. At least placeholders for common functions like `sin!` should be exported from Base so that way libraries like GPU libraries could extend it. I think that’s still pretty clean and very Julia syntax.

---

<div class="post-metadata">

### Author: ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)
#### Post date: [December 5, 2016, 6:19am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/15 "2016-12-05T06:19:54Z")

</div>

@johnmyleswhite I also agree with that - I’ve been experimenting with using the `Transformation` of _CoordinateTransformations.jl_ more generally for stating, planning and executing computations outside of geometry. I feel you could do something like the planning of _Query.jl_ using higher-order functions rather than macros using this approach, and yes, you could break up a vectorized computation into a bunch of introspection-friendly steps.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 6:40am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/16 "2016-12-05T06:40:28Z")

</div>

@ChrisRackauckas I guess my point is that its equivalent to

```julia
broadcast!(sin, cache1, x)
broadcast!(cos, cache2, x)
y .= cache1 .+ cache2

```

Therefore, overriding `broadcast!(::typeof(sin),::GPUVector,::GPUVector)` and `broadcast!(::typeof(cos),::GPUVector,::GPUVector)` would be all that’s necessary, with no need for `sin!` and `cos!`.

If a user called

```julia
broadcast!(x->cos(x) + sin(x),cache1,x)

```

on GPU arrays, it would just error out.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 5, 2016, 6:41am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/17 "2016-12-05T06:41:16Z")

</div>

> [@dlfivefifty](#):
>
> If a user called
> 
> broadcast!(x-\>cos(x) + sin(x),cache1,x)
> 
> on GPU arrays, it would just error out.

But isn’t this what broadcast fusion will automatically do?

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 5, 2016, 6:41am UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/18 "2016-12-05T06:41:44Z")

</div>

So the user should write `broadcast!(cos,cache1,x)` if they don’t want broadcast fusion

---

<div class="post-metadata">

### Author: ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)
#### Post date: [December 6, 2016, 2:17pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/19 "2016-12-06T14:17:12Z")

</div>

I could use additional insight.  
On the one hand there is multidispatch and that had preferred

```
sin(x::TypeOfValue) .. end
sin(xs::Vector{TypeOfValue}) .. end
# and the uses
sin( value )
sin( values )

```

On the other one hand there is broadcasting and that prefers

```
sin(x::TypeOfValue) .. end
# and the uses
sin( value )
sin.( values )

```

Sometimes I do not know this:  
Is my `value` stands alone or is a vector of values or a fixed length array of values?  
In that case I would have been inclined to define `sin{T}( values::Vector{T} ) == sin.(values)`; but that is frowned upon (and, apparently, not costless even if it were accepted).

Is there a [relatively] new perspective that things that are a self-contained thing (as if length([thing…]) ==1) should not be used interchangeably with things that are a sequence of thing (as if length([thing…]) \> 1)?

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [December 6, 2016, 10:13pm UTC](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677/20 "2016-12-06T22:13:43Z")

</div>

`sin.(1)` returns `sin(1)`, So _always_ use `sin.(x)` if you want it to work on both `Vector` and `Number` interchangeably.

[Next page](https://discourse.julialang.org/t/what-is-the-future-of-sin-vector-when-there-is-sin-vector/677.md?page=2)
