I don't understand this bit: "Numpy's notation has the advantage to make the most expensive operations harder to write, it also easily reminds us that arrays in numpy are row-major." How does this make the more expensive operation harder to write?
To me (but I didn't design Julia so what do I know) have a[i] refer to a specific element makes sense because it makes it easy to write a loop that does something to each element without having to worry about the dimensions of the array. On Friday, May 9, 2014 12:53:44 PM UTC+3, [email protected] wrote: > > Hi, my mind might be completely fried by intensive use of numpy arrays, > but I find slicing in Julia quite odd and I'd like to understand why. I'm > not saying Julia *should* behave like numpy but I find numpy's behaviour > really convenient. Let me explain... > > Let say I created a random 2D array in numpy and Julia which is: > a = 0.618734 0.858034 0.261089 > 0.988064 0.323639 0.379946 > 0.571054 0.998853 0.453861 > 0.965824 0.629747 0.210426 > > In numpy, a[0] would give: > 0.618734 0.858034 0.261089 > and in Julia, a[1] would give: > 0.618734 > > In numpy, a[:] would give the whole matrix, in Julia, the flatten matrix. > > From what I've understood, these differences come down to the fact that > numpy arrays are considered as containers. The fact that default operators > act element-wise emphases that fact while Julia's arrays are not considered > only as containers but as algebraic objects. They are well defined in 1D > (vector) and 2D (matrix) but not that much for higher dimensional stuff > (tensors were evoked, with a generalisation of the dot product discussed > here <https://groups.google.com/forum/#!topic/julia-dev/gnizzJAU5RY>). > > In short the differences go down to: a[0] in numpy maps to a[1, :] in > Julia and a[1] in Julia maps to a[0, 0] in numpy in 2D. > > Numpy's notation has the advantage to make the most expensive operations > harder to write, it also easily reminds us that arrays in numpy are > row-major. > > Julia's notation has the advantage of not doing stuff behind your back > (possibly saving a few CPU cycles), but at the expense of increased > verbosity. This is even more obvious when a 3D container should be > considered as a series of matrices: AFAIK, there is no way to cleanly > iterate over them. I'll have to rely on explicite indexing. > > Python: > ref = rand(3,4) # matrix of 3 rows by 4 columns > a = rand(5,4,3) # 5 matrices of 4 rows by 3 columns > for i in a: > print(i.dot(ref)) > or, still in Python: > ref = rand(3,4) > a = rand(5,4,3) > print(a.dot(ref)) > which is way faster than the first one. > > > In Julia in comparison, this is not allowed and one has to rely on > explicit indexing: > ref = rand(3,4) # matrix of 3 rows by 4 columns > a = rand(4,3,5) # matrix of 4 rows by 3 columns, 5 times > #a * ref # Not working (yet) > for i = 1:size(a)[3] > println(a[:, :, i] * ref) > end > > The Python version is less verbose, but more importantly, you don't have > to think of row-major or column-major: if you need to get a transpose > somewhere, that means slower code. Whereas in Julia, println(a[:, :, i] * > ref) could be transformed to println(a[i, :, :] * ref) whithout realising > this could lead to inefficiencies. Of course, this can be written in Python > too, but that would also mean slower code. > > I'm not saying Julia should change and I understand that once a > generalised * operator lands, verbosity and innefficient constructs won't > be a problem anymore. But considering all of that, numpy's behavior still > looks more convenient (and this example runs twice faster on Python than on > Julia which indicates that the performance penalty of returning a matrix > the numpy's way is negligible). > > Why does Julia make the choice to return only one number when the ambigous > a[1] is executed? >
