I have an array of size 330x534x223 containing a distribution of values, like a 3d image. It's size is prohibitively large for my purposes, so I'm looking to resample it by a factor of 20 in each dimension.
Is there any conceivable way to do this? I've tried checking the docs
Thank you
If you're thinking in terms of "thumbnail images," then just taking every 20th element may not be satisfying. For something that will simultaneously smooth and subsample with very good performance, I recommend restrict from JuliaImages (which cuts by a factor of 2, and you can call it repeatedly).
How about this?
julia> subsample(a, n) = getindex(a, (indices(a,i)[1:n:end] for i=1:ndims(a))...)
subsample (generic function with 1 method)
julia> a = reshape(1:10^6, (100,100,100));
julia> subsample(a, 50)
2×2×2 Array{Int64,3}:
[:, :, 1] =
1 5001
51 5051
[:, :, 2] =
500001 505001
500051 505051
This should also work for arrays with unconventional indexing like OffsetArrays.
For large arrays, the overhead of this implementation compared to the direct indexing with ranges is negligible.
Edit:
A type stable version:
subinds(n, inds) = (first(inds)[1:n:end], subinds(n, Base.tail(inds))...)
subinds(n, ::Tuple{}) = ()
subsample(a, n) = getindex(a, subinds(n, indices(a))...)
Related
I want to change only one element, as shown in the code below.
using Flux, CuArrays
a = rand(3,3) |> gpu
CuArrays.allowscalar(false)
a[1, 1] = 1.0f0
Because allowscalar is set to false, it is natural that it will appear as below.
ERROR: scalar setindex! is disallowed
But if allowscalar is removed, it will appear as below.
Performing scalar operations on GPU arrays: This is very slow, consider disallowing these operations with allowscalar(false)
I turned "allowscalar" on and off before and after the part that accesses the element.
Then, it was about 20 times slower than when "allowscalar" was set to true.
Next, I tried to create another matrix once on the CPU and then add up the matrices on the GPU, as shown below.
b = zeros(Float32, 3, 3)
b[1, 1] = 1.0f0
b = b |> gpu
a .+= b
However, it is about 4 times faster if I assume that I can do it on the GPU alone such as below.
a .*= 1.0f0 # Dummy calculations that do some processing on the GPU
a .+= a # Dummy calculations that do some processing on the GPU
How do I access an element in a CuArray and change its value?
I look forward to hearing from you soon.
I turned "allowscalar" on and off before and after the part that accesses the element. Then, it was about 20 times slower than when "allowscalar" was set to true.
Toggling allowscalar should not affect performance. In fact, CuArrays itself does so when it needs to inspect individual elements with certain APIs. A macro version of the function makes it easy to do so:
julia> a = CuArrays.rand(3,3);
julia> CuArrays.allowscalar(false)
julia> a[1, 1] = 1.0f0
ERROR: scalar setindex! is disallowed
julia> CuArrays.#allowscalar a[1, 1] = 1.0f0
1.0f0
julia> a
3×3 CuArray{Float32,2,Nothing}:
1.0 0.277899 0.333898
0.126213 0.0881365 0.794662
0.94518 0.586488 0.656359
julia> a[1, 1] = 1.0f0
I picked up Julia to do some numerical analysis stuff and was trying to implement a full pivot LU decomposition (as in, trying to get an LU decomposition that is as stable as possible). I thought that the best way of doing so was finding the maximum value for each column and then resorting the columns in descending order of their maximum values.
Is there a way of avoiding swapping every element of two columns and instead doing something like changing two references/pointers?
Following up on #longemen3000's answer, you can use views to swap columns. For example:
julia> A = reshape(1:12, 3, 4)
3×4 reshape(::UnitRange{Int64}, 3, 4) with eltype Int64:
1 4 7 10
2 5 8 11
3 6 9 12
julia> V = view(A, :, [3,2,4,1])
3×4 view(reshape(::UnitRange{Int64}, 3, 4), :, [3, 2, 4, 1]) with eltype Int64:
7 4 10 1
8 5 11 2
9 6 12 3
That said, whether this is a good strategy depends on access patterns. If you'll use elements of V once or a few times, this view strategy is a good one. In contrast, if you access elements of V many times, you may be better off making a copy or moving values in-place, since that's a price you pay once whereas here you pay an indirection cost every time you access a value.
Just for "completeness", in case you actually want to swap columns in-place,
function swapcols!(X::AbstractMatrix, i::Integer, j::Integer)
#inbounds for k = 1:size(X,1)
X[k,i], X[k,j] = X[k,j], X[k,i]
end
end
is simple and fast.
In fact, in an individual benchmark for small matrices this is even faster than the view approach mentioned in the other answers (views aren't always free):
julia> A = rand(1:10,4,4);
julia> #btime view($A, :, $([3,2,1,4]));
31.919 ns (3 allocations: 112 bytes)
julia> #btime swapcols!($A, 1,3);
8.107 ns (0 allocations: 0 bytes)
in julia there is the #view macro, that allows you to create an array that is just a reference to another array, for example:
A = [1 2;3 4]
Aview = #view A[:,1] #view of the first column
Aview[1,1] = 10
julia> A
2×2 Array{Int64,2}:
10 2
3 4
with that said, when working with concrete number types (Float64,Int64,etc), julia uses contiguous blocks of memory with the direct representation of the number type. that is, a julia array of numbers is not an array of pointers were each element of an array is a pointer to a value. if the values of an array can be represented by a concrete binary representation (an array of structs, for example) then an array of pointers is used.
I'm not a computer science expert, but i observed that is better to have your data tightly packed that using a lot of pointers when doing number crunching.
Another different case is Sparse Arrays. the basic julia representation of an sparse array is an array of indices and an array of values. here you can simply swap the indices instead of copying the values
I'm new to Julia and wonder what is the best way to get the index of subarray, consider the following array of vectors
vec = [[1, 2, 3], [4, 5, 6]]
I would like to get the index of the element [4, 5, 6], however I can not use getindex(), execution of the following code:
getindex(vec, [1, 2, 3])
gives:
BoundsError: attempt to access 2-element Array{Array{Int64,1},1} at index [[1, 2, 3]]
So I wonder if there are any effective build-in methods for doing this. Of course I can map this array of vectors into another array of numbers and do a search inside new array of numbers, but it isn't really a solution what I expect.
Second question is how do I learn more about search methods in Julia and their performances. I guess the theoretical speed of search scales like \sqrt(N) however depending on the certain method the real code time may vary significantly.
Judging by the name of the function you might be mislead: getindex retrieves the value stored at an index.
If you want to find the index of something in an array you can make use of find* methods findfirst, findall...
julia> vec=[[1,2,3],[4,5,6]]
2-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
julia> i = findfirst(x->x==[4,5,6],vec)
2
julia> vec[i]
3-element Array{Int64,1}:
4
5
6
Concerning your second question:
It's best to inform yourself about search/sort algorithms in general (e.g. https://codeburst.io/algorithms-i-searching-and-sorting-algorithms-56497dbaef20?gi=3bdbf8cbaca0), because the performance depends much more on the chosen algorithm than on the language specific implementation. E.g. time complexity can be very different (O(n), O(log(n),...).
I think you've misunderstood what getindex does. It's the function that gets called by [], so
julia> getindex(vec, 2)
3-element Array{Int64,1}:
4
5
6
All search (or "find") methods in Julia take a function as it's first argument, and find where the function evaluates to true. To find a particular element, use isequal or == (they are equivalent):
julia> findall(==([1,2,3]), vec)
1-element Array{Int64,1}:
1
I would like to do the inverse of matrix or number by multiplyig a vector with its trasposed but it gives me an error.
v=[1,2,3]
inv(v'*v)
`inv` has no method matching inv(::Array{Int64,1})
while loading In[45], in expression starting on line 2
I would like to obtain a number or a square matrix at the end.
I do not want to use pinv function because i need to do further manipulations and i need exactly a number or a square matrix.
How to fix this? Thanks in advance
v is a 3-element vector and v'*v is a 1-element vector:
julia> v = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> v'*v
1-element Array{Int64,1}:
14
You cannot invert a vector. If you want to compute the scalar dot product of v with itself, you can use the dot function and then invert it using inv:
julia> dot(v,v)
14
julia> inv(dot(v,v))
0.07142857142857142
This comes long after the question was asked, but maybe it is useful for someone. To elaborate a little:
[1, 2, 3] is a vector or one-dimensional (of type Array{Int64,1} or Vector{Int64})
[1 2 3] is a 1x3 matrix (of type Array{Int64,2})
[1 2 3]' is (is essence) a 3x1 matrix (of type Array{Int64,2}). This is not quite right, it is really a lazy (non-evaluated) version of it, but it will behave as it should
So what you want to achieve can be done as follows:
v = [1 2 3]
display(v' * v)
inv(v' * v)
This fails now for the right reason :-), i.e., the 3x3 matrix is not invertible.
BTW, you can convert a vector v (of type Vector{T} and length n) into an n×1-array of type Array{T,2} with hcat(v).
I was delighted to learn that Julia allows a beautifully succinct way to form inner products:
julia> x = [1;0]; y = [0;1];
julia> x'y
1-element Array{Int64,1}:
0
This alternative to dot(x,y) is nice, but it can lead to surprises:
julia> #printf "Inner product = %f\n" x'y
Inner product = ERROR: type: non-boolean (Array{Bool,1}) used in boolean context
julia> #printf "Inner product = %f\n" dot(x,y)
Inner product = 0.000000
So while i'd like to write x'y, it seems best to avoid it, since otherwise I need to be conscious of pitfalls related to scalars versus 1-by-1 matrices.
But I'm new to Julia, and probably I'm not thinking in the right way. Do others use this succinct alternative to dot, and if so, when is it safe to do so?
There is a conceptual problem here. When you do
julia> x = [1;0]; y = [0;1];
julia> x'y
0
That is actually turned into a matrix * vector product with dimensions of 2x1 and 1 respectively, resulting in a 1x1 matrix. Other languages, such as MATLAB, don't distinguish between a 1x1 matrix and a scalar quantity, but Julia does for a variety of reasons. It is thus never safe to use it as alternative to the "true" inner product function dot, which is defined to return a scalar output.
Now, if you aren't a fan of the dots, you can consider sum(x.*y) of sum(x'y). Also keep in mind that column and row vectors are different: in fact, there is no such thing as a row vector in Julia, more that there is a 1xN matrix. So you get things like
julia> x = [ 1 2 3 ]
1x3 Array{Int64,2}:
1 2 3
julia> y = [ 3 2 1]
1x3 Array{Int64,2}:
3 2 1
julia> dot(x,y)
ERROR: `dot` has no method matching dot(::Array{Int64,2}, ::Array{Int64,2})
You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
The error message suggestion is dot(vec(x),vec(y), but sum(x.*y) also works in this case and is shorter.
julia> sum(x.*y)
10
julia> dot(vec(x),vec(y))
10
Now, you can write x⋅y instead of dot(x,y).
To write the ⋅ symbol, type \cdot followed by the TAB key.
If the first argument is complex, it is conjugated.
Now, dot() and ⋅ also work for matrices.
Since version 1.0, you need
using LinearAlgebra
before you use the dot product function or operator.