Transpose matrix with MPI_Alltoallv - c

I'd like to transpose a matrix b using MPI_Alltoallv and store it in bt.
Each process contain nlocal rows of b. For example:
Proc0: 0 | 10 | 20 | 30
Proc0: 1 | 11 | 21 | 31
Proc1: 100 | 110 | 120 | 130
Proc1: 101 | 111 | 121 | 131
I'd like bt being like:
Proc0: 0 | 1 | 100 | 101
Proc0: 10 | 11 | 110 | 111
Proc1: 20 | 21 | 120 | 121
Proc1: 30 | 31 | 130 | 131
The submatrices are stored in 2d arrays (b[0] contains the first row and b[1] the second row).
As suggested, I used MPI_Alltoallv(). Here is what I did:
int n=4; //matrix of size 4x4
int nlocal=n/nbProc; // the submatrices are of size 2x4
int sc[nbProc];
int dis[nbProc];
int rdis[nbProc];
for(int i=0;i<nbProc;i++){
sc[i]=1;
}
for(int i=0;i<nlocal;i++){//loop on the b[i]
for(int j=0;j<nlocal;j++){ //loop on the bt[j]
for(int k=0;k<nbProc;k++){
dis[k] = j+k*nlocal;
rdis[k] = i+k*nlocal;
}
MPI_Alltoallv(b[i],sc,dis,MPI_INT,bt[j],sc,rdis,MPI_INT,MPI_COMM_WORLD);
}
}
However, I have 3 loops, I thought that I might have less. Is there anything wrong ?

I found a solution to call MPI_Alltoallv just once. All the submatrices have to be stored in one vector. But instead of storing for n first values, the first line, then the n next values, the second line etc... we store the m values which will go in the first process, the p next the ones which will go in the second process, etc... In the example I wrote, we would have buf = {0,10,1,11,20,30,21,31} for the first process. Then we use MPI_Alltoallv to send the values in a vector (called buft for example) and we then distribute the values in the matrix.
Note that there are two ways of storing the values in buf. The second one is buf={0,1,10,11,20,21,30,31} which is the one I used since I thought it was easier to implement, but the idea remains the same.
Also, this works even if the processes don't have submatrices of the same size (for example if our Proc1 would just have had 1 line in b).

Related

make x in a cell equal 8 and total

I need an excel formula that will look at the cell and if it contains an x will treat it as a 8 and add it to the total at the bottom of the table. I have done these in the pass and I am so rusty that I cannot remember how I did it.
Generally, I try and break this sort of problem into steps. In this case, that'd be:
Determine if a cell is 'x' or not, and create new value accordingly.
Add up the new values.
If your values are in column A (for example), in column B, fill in:
=if(A1="x", 8, 0) (or in R1C1 mode, =if(RC[-1]="x", 8, 0).
Then just sum those values (eg sum(B1:B3)) for your total.
A | B
+---------+---------+
| VALUES | TEMP |
+---------+---------+
| 0 | 0 <------ '=if(A1="x", 8, 0)'
| x | 8 |
| fish | 0 |
+---------+---------+
| TOTAL | 8 <------ '=sum(B1:B3)'
+---------+---------+
If you want to be tidy, you could also hide the column with your intermediate values in.
(I should add that the way your question is worded, it almost sounds like you want to 'push' a value into the total; as far as I've ever known, you can really only 'pull' values into a total.)
Try this one for total sum:
=SUMIF(<range you want to sum>, "<>" & <x>, <range you want to sum>)+ <x> * COUNTIF(<range you want to sum>, <x>)

How can I set a matrix with different, repeating patterns in every column?

I'm trying to set an nx3 matrix in GNU Octave to scatter plot and compare it to a fitted surface which I already solved for and plotted. However this matrix has repeating patterns in columns 1 and 2; I could set them by hand, but the number of rows is somewhat big and the only row I currently have is the non-repeating one (row 3).
For example:
A=|1 5 z|
|2 5 z|
|3 5 z|
|4 5 z|
|1 10 z|
|2 10 z|
...
And so on. Where z are the values that I already have as a column vector, which I can simply punch into the matrix with:
A(:,3)=z
However, I've tried doing
A(2:4:n)=2;A(3:4:n)=3;A(4:4:n)=4
Which actually worked, for the first column, but had no luck with the second one (and I don't think is the cleanest way to do it). Any ideas?
It seems to me that the pattern in the first two columns correspond to a grid of coordinates, where x=1:4 and y=5:5:20 (or some other end value).
You can generate these coordinates using meshgrid:
[y, x] = meshgrid(5:5:20, 1:4);
(Note how x and y are reversed, don't ask). Next, you can put these into a matrix together with the z values you already have as follows:
A = [x(:), y(:), z];
Alternatively, you can do
A(:,1) = x(:);
A(:,2) = y(:);
Each of the column is repeating in a different way so you can generate each in different ways:
octave:1> col1 = repmat ([1:4].', [3 1]); # repeat matrix
octave:2> col2 = ([5 5 5 5].' .* [1 2 3])(:); # automatic broadcasting
octave:3> col3(1:12, 1) = 42; # on the fly by assignment
octave:4> A = [col1 col2 col3]
A =
1 5 42
2 5 42
3 5 42
4 5 42
1 10 42
2 10 42
3 10 42
4 10 42
1 15 42
2 15 42
3 15 42
4 15 42

Importing the result of a MATLAB numeric array into a new MATLAB script

Consider that I have a code that returns a double array. When run, the result returned at the command window a result looks like this:
mpc.gen=
1 100 344 34 5
2 433 223 45 2
3 333 432 12 3
4 213 233 12 3
What I want to do is create a MATLAB script which would contain this array. In other words in this new MATLAB script I would have the following array, constructed like this:
mpc.gen= [ 1 100 344 34 5 ;
2 433 223 45 2 ;
3 333 432 12 3 ;
4 213 233 12 3 ;
] ;
Just calling the function would save the variable in the new script, however that is not what I need since I need to use this script for a simulation at a special power tool called MATPOWER. The array needs to be in the form shown at the new script.
The actual array is much bigger in size however I use this here for simplicity. Is there any way I can do this automatically, and not just pass the data from the command window to the new script one by one manually? Any help would be greatly appreciated. Thank you in advance for your time!
What you want to use is mat2str. It converts a matrix to a string representation that, when evaluated, results in the identical matrix.
For example:
>> result = [1 100 344 34 5;
2 433 223 45 2;
3 333 432 12 3;
4 213 233 12 3];
>> mat2str(result)
ans =
[1 100 344 34 5;2 433 223 45 2;3 333 432 12 3;4 213 233 12 3]
You could write this to a file like so:
f = fopen('test_script.m', 'w');
fprintf(f,'mpc.gen = %s\n', mat2str(result));
fclose(f);
The formatting is not identical to your example, but if the tool does proper MATLAB parsing, it shouldn't be a problem.
Is it intentional that mpc is a struct? (you are using dot in the name.) In the following, I use underscore instead, but it can certainly be adopted, if it is intentional.
This is what functions are for. So instead of making a script, you should create a new function. If I were to do what you want to do, I would have 2 functions and 1 script. Whereas the script looks like this
mpc_bus = function1;
function2(mpc_bus);
where function1 is the code that returns mpc.bus and function2 is the one where you want to work with mpc.gen, and the top would be something like this
function [] = function2(mpc_gen)
Alternatively: If you of some reason does not like functions, you can make the first code save the variable using save(*filename*.mat) and then you can load the file again in the script using dat=load(*filename*.mat); and mpc_gen = dat.mpc_bus;

C - MPI: Parallel Processing of Column Arrays

I have a matrix (c) of 10x10 (M = 10) elements in which I divide the matrix by rows to be executed by 5 different processes (slaves = 5) with each process corresponding to 2 rows of that matrix.
offset = 0;
rows = (M / slaves);
MPI_Send(&c[offset][0], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
offset= offset+rows;
Now I want to divide the matrix but by columns. I did the test as follows by changing array indices but not working:
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
Do you know how to do it? Thank you.
You are using the wrong datatype. As noted by Jonathan Dursi, you need to create a strided datatype that tells MPI how to access the memory in such a way that it matches the data layout of a column or a set of consecutive columns.
In your case, instead of
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave, 0, MPI_COMM_WORLD);
you have to do:
MPI_Datatype dt_columns;
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns);
MPI_Type_commit(&dt_columns);
MPI_Send(&c[0][offset], 1, dt_columns, id_slave, 0, MPI_COMM_WORLD);
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns) creates a new MPI datatype that consists of M blocks of rows elements of MPI_DOUBLE each with the heads of the consecutive blocks M elements apart (stride M). Something like this:
|<------------ stride = M ------------->|
|<---- rows --->| |
+---+---+---+---+---+---+---+---+---+---+--
| x | x | x | x | | | | | | | ^
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
. . . . . . . . . . . M blocks
+---+---+---+---+---+---+---+---+---+---+
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | v
+---+---+---+---+---+---+---+---+---+---+--
>> ------ C stores such arrays row-wise ------ >>
If you set rows equal to 1, then you create a type that corresponds to a single column. This type cannot be used to send multiple columns though, e.g., two columns, as MPI will look for the second one there, where the first one ends, which is at the bottom of the matrix. You have to tell MPI to pretend that a column is just one element wide, i.e. resize the datatype. This can be done using MPI_Type_create_resized:
MPI_Datatype dt_temp, dt_column;
MPI_Type_vector(M, 1, M, MPI_DOUBLE, &dt_temp);
MPI_Type_create_resized(dt_temp, 0, sizeof(double), &dt_column);
MPI_Type_commit(&dt_column);
You can use this type to send as many columns as you like:
// Send one column
MPI_Send(&c[0][offset], 1, dt_column, id_slave, 0, MPI_COMM_WORLD);
// Send five columns
MPI_Send(&c[0][offset], 5, dt_column, id_slave, 0, MPI_COMM_WORLD);
You can also use dt_column in MPI_Scatter[v] and/or MPI_Gather[v] to scatter and/or gather entire columns.
The problem with your code is the following:
your c array is continuous in memory, and in C it stored row-major order, and the dividing it by row like you do will just add constant offset from the beginning.
and the way you are going to divide it by columns just gives you wrong offset.
You can imagine it for 3x3 matrix and 3 slave processes:
a[3][3] = {{a00 a01 a02},
{a10 a11 a12},
{a20 a21 a22}}
which is actually in memory looks like:
A = {a00,a01,a02,a10,a11,a12,a20,a21,a22}
For example we want to send data to CPU with id = 1. In this case a[1][0] will point you to the forth element of A and the a[0][1] will point you to the second element of A. And the in both cases you just send the rows*M elements from the specific point in A.
In first case it will be:
a10,a11,a12
And in second case:
a01,a02,a10
One of the way to solve things you want is to transpose your matrix and the send it.
And also it is much natural to use MPI_Scatter than MPI_Send for this problem,
something like it explained here: scatter

Find product of integers at interval of X and update value at position 'i' in an array for N queries

I have given an array of integers of length up to 10^5 & I want to do following operation on array.
1-> Update value of array at any position i . (1 <= i <= n)
2-> Get products of number at indexes 0, X, 2X, 3X, 4X.... (J * X <= n)
Number of operation will be up to 10^5.
Is there any log n approach to answer query and update values.
(Original thought is to use Segment Tree but I think that it is not needed...)
Let N = 10^5, A:= original array of size N
We use 0-based notation when we saying indexing below
Make a new array B of integers which of length up to M = NlgN :
First integer is equal to A[0];
Next N integers is of index 1,2,3...N of A; I call it group 1
Next N/2 integers is of index 2,4,6....; I call it group 2
Next N/3 integers 3,6,9.... I call it group 3
Here is an example of visualized B:
B = [A[0] | A[1], A[2], A[3], A[4] | A[2], A[4] | A[3] | A[4]]
I think the original thoughts can be used without even using Segment Tree..
(It is overkill when you think for operation 2, we always will query specific range on B instead of any range, i.e. we do not need that much flexibility and complexity to maintain the data structure)
You can create the new array B described above, also create another array C of length M, C[i] := products of Group i
For operation 1 simply use O(# factors of i) to see which Group(s) you need to update, and update the values in both B and C (i.e. C[x]/old B[y] *new B[y])
For operation 2 just output corresponding C[i]
Not sure if I was wrong but this should be even faster and should pass the judge, if the original idea is correct but got TLE
As OP has added a new condition: for operation 2, we need to multiply A[0] as well, so we can special handle it. Here is my thought:
Just declare a new variable z = A[0], for operation 1, if it is updating index 0, update this variable; for operation 2, query using the same method above, and multiply by z afterwards.
I have updated my answer so now I simply use the first element of B to represent A[0]
Example
A = {1,4,6,2,8,7}
B = {1 | 4,6,2,8,7 | 6,8 | 2 | 8 | 7 } // O(N lg N)
C = {1 | 2688 | 48 | 2 | 8 | 7 } // O (Nlg N)
factorization for all possible index X (X is the index, so <= N) // O(N*sqrt(N))
opeartion 1:
update A[4] to 5: factors = 1,2,4 // Number of factors of index, ~ O(sqrt(N))
which means update Group 1,2,4 i.e. the corresponding elements in B & C
to locate the corresponding elements in B & C maybe a bit tricky,
but that should not increase the complexity
B = {1 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(sqrt(N))
C = {1 | 2688 | 48/8*5 | 2 | 8/8*5 | 7 } // O(sqrt(N))
update A[0] to 2:
B = {2 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(1)
C = {2 | 2688/8*5 | 48/8*5 | 2 | 8/8*5 | 7 } // O(1)
// Now A is actually {2,4,6,2,5,7}
operation 2:
X = 3
C[3] * C[0] = 2*2 = 4 // O(1)
X = 2
C[2] * C[0] = 30*2 = 60 // O(1)

Resources