I try to keep some computation results in each workers and fetch them together after all computation is done. However, I could not actually modify the variable of the workers.
Here is a simplified example
using Distributed
addprocs(2)
#everywhere function modify_x()
global x
x += 1
println(x) # x will increase as expected
end
#everywhere x = 0
#sync #distributed for i in 1:10
modify_x()
end
fetch(#spawnat 2 x) # gives 0
This sample tries to modify x contained in each worker. I expect x to be like 5, but the final fetch gives the initial value 0
By running fetch(#spawnat 2 x) you unintentionally transferred the value of x from the current worker to worker 2.
See this example:
julia> x = 3
3
julia> fetch(#spawnat 2 x)
3
If you want to retrieve the value of x, you could try the following:
julia> #everywhere x = 0
julia> #sync #distributed for i in 1:10
modify_x()
end
From worker 3: 1
From worker 3: 2
From worker 3: 3
From worker 3: 4
From worker 3: 5
From worker 2: 1
From worker 2: 2
From worker 2: 3
From worker 2: 4
Task (done) #0x000000000d34a6d0 From worker 2: 5
julia> #everywhere function fetch_x()
return x
end
julia> fetch(#spawnat 2 fetch_x())
5
See https://docs.julialang.org/en/v1/manual/distributed-computing/#Global-variables
Related
In terms of usage API is there diference between call n times a 1 X n calculatematrix and call 1 time a n x n calculatematrix?
For example, if I need a matrix of 3 origens and 3 destinations. Is there difference of cost if I call 3 times a calculatematrix with 1 origen and 3 destinations or I call one time a calculatematrix with 3 origens and 3 destinations?
I am trying to learn parallel for loop in Julia, while I was confused by the result of the example code below:
addprocs(4)
#everywhere begin
N = 10
V = SharedArray{Int64,1}(N)
#sync #parallel for i = 1:N
V[i] = i
println(V[i])
end
end
By using println, I tried to identify which worker went through which step. Surprisingly, what I got from the above code was that each worker kept going through the entire iteration until the last worker (worker 3 in my case) finished the for loop:
From worker 4: 1
From worker 4: 2
From worker 4: 3
From worker 5: 1
From worker 5: 2
From worker 5: 3
From worker 5: 4
From worker 5: 5
From worker 5: 6
From worker 5: 4
From worker 5: 5
From worker 5: 6
From worker 2: 7
From worker 2: 8
From worker 2: 4
From worker 2: 5
From worker 2: 6
From worker 2: 9
From worker 2: 10
From worker 4: 1
From worker 4: 2
From worker 2: 7
From worker 2: 8
From worker 3: 9
From worker 5: 4
From worker 5: 5
From worker 5: 6
From worker 3: 10
From worker 3: 7
From worker 3: 8
From worker 3: 7
From worker 3: 8
From worker 3: 9
From worker 3: 10
From worker 2: 4
From worker 2: 5
From worker 2: 6
From worker 3: 7
From worker 3: 8
From worker 4: 3
From worker 4: 9
From worker 4: 10
From worker 4: 1
From worker 4: 2
From worker 4: 3
From worker 4: 1
From worker 4: 2
From worker 4: 3
From worker 5: 9
From worker 5: 10
This is not what I would expect from parallel for loop, as I thought the work should be distributed among the workers and then combined together, rather than being done separately for each of the worker. I mean, should the concept of parallel for loop be that each worker only goes through 2-3 steps?
Is something wrong with my code or I misunderstand the concept of parallel for loop?
Thanks!
Edit: I just realized that there is something to do with #everywhere. After I eliminated #everywhere, things work as expected.
You told julia (through #everywhere) to run the parallel loop on every worker and on the host process, hence you count from 1 to 10 in a parallel fashion 5 times. (Check that in the output you posted every number from 1 to 10 occurs precisely 5 times)
Slightly more detailed: First we note that the total number of processes is nprocs() == 5 (one "host" and 4 workers, check workers()). #everywhere tells Julia to run the content of the begin end block on every process, hence 5 times in our example. The content of the begin end block is "do a parallel loop, counting from 1 to 10". That is exactly what happened.
When you remove the #everywhere you do just a single parallel loop. Thus you will get exactly what you want:
julia> N = 10
V = SharedArray{Int64,1}(N)
#sync #parallel for i = 1:N
V[i] = i
println(V[i])
end
From worker 5: 9
From worker 5: 10
From worker 3: 4
From worker 3: 5
From worker 3: 6
From worker 2: 1
From worker 2: 2
From worker 2: 3
Suggested reading: https://docs.julialang.org/en/stable/manual/parallel-computing
I have a requirement for a for loop in Elixir that returns a calculated value.
Here is my simple example:
a = 0
for i <- 1..10
do
a = a + 1
IO.inspect a
end
IO.inspect a
Here is the output:
warning: variable i is unused
Untitled 15:2
2
2
2
2
2
2
2
2
2
2
1
I know that i is unused and can be used in place of a in this example, but that's not the question. The question is how do you get the for loop to return the variable a = 10?
You cannot do it this way as variables in Elixir are immutable. What your code really does is create a new a inside the for on every iteration, and does not modify the outer a at all, so the outer a remains 1, while the inner one is always 2. For this pattern of initial value + updating the value for each iteration of an enumerable, you can use Enum.reduce/3:
# This code does exactly what your code would have done in a language with mutable variables.
# a is 0 initially
a = Enum.reduce 1..10, 0, fn i, a ->
new_a = a + 1
IO.inspect new_a
# we set a to new_a, which is a + 1 on every iteration
new_a
end
# a here is the final value of a
IO.inspect a
Output:
1
2
3
4
5
6
7
8
9
10
10
I'm performing input-output calculations in Octave. I have several matrices/vectors in the formula:
F = f' * (I-A)^-1 * Y
All vectors probably contain zeroes. I would like to omit them from the calculation and just return 0 instead. Any help would be greatly appreciated!
Miranda
What do you mean when you say "omit them"?
If you want to remove zeros from a vector you can do this:
octave:1> x=[1,2,0,3,4,0,5];
octave:2> x(find(x==0))=[]
x =
1 2 3 4 5
The logic is: x==0 will test each element of x (in this case the test is if it equals zero) and will return a vector of 0's and 1's (0 if the test is false for that element and 1 otherwise)
So:
octave:1> x=[1,2,0,3,4,0,5];
octave:2> x==0
ans =
0 0 1 0 0 1 0
The find() function will return the index value of any non-zero element of it's argument, hence:
octave:3> find(x==0)
ans =
3 6
And then you are just indexing and removing when you do something like:
octave:5> x([3, 6]) = []
x =
1 2 3 4 5
But instead you do it with the output of the find() function (which is the vector [3,6] in this case)
You can do the same for matrices:
octave:7> A = [1,2,0;4,5,0]
A =
1 2 0
4 5 0
octave:8> A(find(A==0))=[]
A =
1
4
2
5
Then use the reshape() function to turn it back into a matrix.
Using Julia, I'd like to determine if a row is located in a matrix and (if applicable) where in the matrix the row is located. For example, in Matlab this can done with ismember:
a = [1 2 3];
B = [3 1 2; 2 1 3; 1 2 3; 2 3 1]
B =
3 1 2
2 1 3
1 2 3
2 3 1
ismember(B, a, 'rows')
ans =
0
0
1
0
From this, we can see a is located in row 3 of B. Is there a similar function to accomplish this in Julia?
You can also make use of array broadcasting by simply testing for equality (.==) without the use of comprehensions:
all(B .== a, dims=2)
Which gives you:
4x1 BitMatrix:
0
0
1
0
You can then use findall on this array:
findall(all(B .== a, 2))
However, this gives you a vector of CartesianIndex objects:
1-element Vector{CartesianIndex{2}}:
CartesianIndex(3, 1)
So if you expect to find multiple rows with the value defined in a you can either:
simplify this Vector by taking only the row index from each CartesianIndex:
[cart_idx[1] for cart_idx in findall(all(B .== a, 2))]
or pass one dimensional BitMatrix to findall (as suggested by Shep Bryan in the comment):
findall(all(B .== a, dims=2)[:, 1])
Either way you get an integer vector of column indices:
1-element Vector{Int64}:
3
Another pattern is using array comprehension:
julia> Bool[ a == B[i,:] for i=1:size(B,1) ]
4-element Array{Bool,1}:
false
false
true
false
julia> Int[ a == B[i,:] for i=1:size(B,1) ]
4-element Array{Int64,1}:
0
0
1
0
how about:
matchrow(a,B) = findfirst(i->all(j->a[j] == B[i,j],1:size(B,2)),1:size(B,1))
returns 0 when no matching row, or first row number when there is one.
matchrow(a,B)
3
should be as "fast as possible" and pretty simple too.
Though Julia doesn't have a built-in function, its easy enough as a one-liner.
a = [1 2 3];
B = [3 1 2; 2 1 3; 1 2 3; 2 3 1]
ismember(mat, x, dims) = mapslices(elem -> elem == vec(x), mat, dims)
ismember(B, a, 2) # Returns booleans instead of ints