View with single value

I want to pass a single value from an array to a function, and I thought this could be faster using view. However, since view returns not an integer but an array, if the function receives an integer at that position, the operations with it do not work. This minimal example illustrates what I am trying to say:

julia> x = [1, 2]
2-element Array{Int64,1}:
 1
 2

julia> i = view(x,1,1)
0-dimensional view(::Array{Int64,2}, 1, 1) with eltype Int64:
1

julia> view(x,1,1) == 1
false

In other words, is there a way to pass scalars by reference?

Thank you.

The overhead associated with creating the view will be much greater than the cost of passing in a single integer. Could you zoom out a bit and describe more broadly what you’re trying to do?

5 Likes

Plain scalar values are the fastest you can get. I don’t see how a heap-allocated array with a view on top could be faster.

1 Like

Your problem here is that, unlike in C, you need to unwrap the reference first if you want the actual value. You can access the element with view(x, 1, 1)[] and can also change the value in the original array like this. You won’t get any performance benefits, but this is still useful if you want to mutate the underlying array.

Ok, good to know. I have to pass those values many, many times, and I am trying to find out the fastest way to do it. I thought that this was a possibility of accelerating things, but if not, I will try something else. Thank you.

You can use Ref(x) to pass a reference to a scalar x.

In C you have to dereference a pointer too for values passed “by reference”, and in C++ for reference (T&) there is still a pointer dereference happening under the hood.

For an individual parameter, passing it directly will generally be the fastest thing to do. If you have a large number of parameters that you are passing around together, you might put them together into a struct, for clarity if not for performance.

In general, however, I would begin by optimizing your program for clarity, correctness, and composability. Only worry about performance later, after doing some measurements — your mental model for which operations are slow and which are fast could be quite unreliable.

4 Likes

Thank you. I was passing some elements of a very large four-dimensional matrix, and I had to search in a vector of non-zero values of the matrix for the corresponding elements. I thought that passing the elements by copy would be a time bottleneck, but knowing that this is not the case I improved the structure of the code and got it to run thousands of times faster :-). I am quite experienced with code optimization but, with a recent Fortran background, sometimes I do not know the performance issues concerning parameter passing, because in Fortran everything goes by reference. I am learning these differences now. Anyway, problem solved. Moving to the next one, :slight_smile:

The way to think about it is that an int is 4 bytes, and although I don’t know what a view is, it almost certainly has a pointer which is 8. Copying a few bytes will always be faster than passing a reference to them which is larger.

Actually, Ints are 8 bytes.

1 Like

It depends on if you use 64 or 32 bit Julia.

Well, the OP, and probably the vast majority of everyone use Int64.

Anyway, I was reacting to the blanket statement that Ints are 4 bytes.

1 Like

Hi there,

I don’t know if I should make a new post or try to revive this one, since I’ve run into the same issue from the title. I have a problem where I compute the forward derivative of many functions - it is much faster to pair these functions up and compute their forward derivative all at once. The problem is that I still want the result of the functions split up into a list of structures, which I have been doing with single-element views.

The forward derivative is computed in place, and is updated many times, so it would be quite slow to do a pass where I update the list of structs, and the code would look very messy if I operated on the array directly. Is there a way to point at a single element of the array - I feel like this would clean up my code a bit, and give a slight performance gain.

Is it? Why is that?

So it’s one big computation to compute the state of a system, and then a bunch of functions that use the state of the system. It would be nice to split it up using the tangent functor and compute:

(T.f_i) \circ T.g

rather than

T.(f_i \circ g)

But that ends up being slower and using much more memory than computing everything in place.

Just for the records, my original question was more related to my lack of understanding of the differences between mutable and immutable variables. I don’t remember where exactly I had that issue, but certainly from the question now I would use a function operating on a immutable scalar, which returns the new value to be used to mutate the value in the original array.

3 Likes