I have a Cartesian process topology in 3D. However, I describe my problem in 2D to simplify it.
For the collective nearest neighbor communication (left image) I use MPI_Neighbor_alltoallw() which allows send and receive of different datatypes. However this function does not work for diagonal neighbors (right image) and I need another function for diagonal neighbors.
Left: nearest neighbors are green neighbors. Right: red grids are nearest diagonal neighbor.
What I have in my mind to implement diagonal neighbor communication is:
int main_rank; // rank of the gray process
int main_coords[2]; // coordinates of the gray process
MPI_Comm_rank (comm_cart, &main_rank);
MPI_Cart_coords (comm_cart, main_rank, 2, main_coords);
// finding the rank of the top-right neighbor
int top_right_rank;
int top_right_coords[2] = {main_coords[0]+1, main_coords[1]+1};
MPI_Cart_rank (comm_cart, top_right_coords, &top_right_rank);
// SEND DATA: MPI_Isend(...);
// RECEIVE DATA: MPI_Irecv(...);
// MPI_Waitall(...);
// REPEAT FOR OTHER DIAGONAL NEIGHBORS
Question
Is there any collective diagonal neighborhood communication in MPI standard?
What is the efficient and less error-prone implementation?
Do you have any suggestion to make my implementation better?
This is a common question of how to update ghost cells/halos in MPI... In Fact there is an elegant solution to this problem.... THERE IS NO NEED OF DIAGONAL COMMUNICATION :-).
So how to do it without those painful diagonals :-)...
Lets do a simple example of a 2-torus (2x2) with 4 processes and a 1 sized halo.
x x x x x x
x 1 x x 2 x
x x x x x x
x x x x x x
x 3 x x 4 x
x x x x x x
First lets work on the vertical direction:
Here we only send that data outside the ghost cells.
x 3 x x 4 x
x 1 x x 2 x
x 3 x x 4 x
x 1 x x 2 x
x 3 x x 4 x
x 1 x x 2 x
Now lets work out the horizontal direction... But this time we also send the ghost cells...
x 3 x 3 x 4 x
x 1 x -> 1 ->x 2 x
x 3 x 3 x 4 x
So we get:
4 3 4 3 4 3
2 1 2 1 2 1
4 3 4 3 4 3
4 1 2 1 2 1
4 3 4 3 4 3
2 1 2 1 2 1
That is the elegant (and most efficient) way of doing it... diagonals communication are replaced by 2 communication (which are needed during the process anyway)....
Related
This
n = length(s)
# n = 25920169
nfft = 8192
noverlap = Int64(floor(nfft/2))
window = hanning(nfft)
#sp = spectrogram(s, n, noverlap; nfft=nfft, fs=1, window=window)
sp = periodogram(s; nfft=nfft, fs=1, window=window)
throws the error
nfft must be >= n
But the documentation says:
If length(s) < nfft, then the input is padded with zeros.
Doesn't it mean that nfft < n should be correct?
I think that the FFT length nfft should be greater than the signal length n to prevent aliasing.
The periodogram function uses FFT internally, where the length is denoted as nfft. In theory, when using FFT, the signal in both time domain and frequency domain are discrete and periodic, where the period is given by nfft. So, if you specify an nfft that is less than the signal length n, this actually introduces aliasing in the time domain to make the signal periodic with nfft.
For example, if you have a sequence 1 2 3 4 5, assuming that your period is also 5, you have
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
--------------------------------
... 1 2 3 4 5 ...
i.e., the original sequence. Now assume you have a period of 3, then it looks like
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
------------------------
... 5 7 3 ...
When you take FFT of this sequence with n > nfft, you are working with this aliased sequence.
You can manually allow for n > nfft by applying the wrap(x,nfft) as bellow and feeding its output to periodogram, MATLAB does exactly that.
function wrap(x,nfft)
y = zeros(eltype(x),nfft)
for (i,xi) in enumerate(x)
y[mod1(i,nfft)] += xi
end
y
end
For example:
wrap(1:5,3)
3-element Vector{Int64}:
5
7
3
I'm looking for an easy way to add the minimum value for each column inside my dataframe.
This feels like a common thing, but I haven't been able to find any good answers yet...maybe I'm missing something obvious.
Let's say I've got two columns (in reality I have close to 100) with positive and negative numbers.
w <- c(9, 9, 9, 9)
x <- c(-2, 0, 1, 3)
y <- c(-1, 1, 3, 4)
z <- as.data.frame(cbind(w, x, y))
w x y
1 9 -2 -1
2 9 0 1
3 9 1 3
4 9 3 4
I want z to look like this after a transformation for only x and y columns [,2:3]
w x y
1 9 0 0
2 9 2 2
3 9 3 4
4 9 5 5
Does that make sense?
library(dplyr)
dplyr::mutate(z, across(c(x, y), ~ . + abs(min(.))))
w x y
1 9 0 0
2 9 2 2
3 9 3 4
4 9 5 5
You can also do by column position rather than column name by changing c(x,y) to 2:3 or c(2:3, 5) for non-sequential column positions.
Depends exactly what you mean and what you want to happen if there aren't negative values. No matter the values, this will anchor the minimum at 0, but you should be able to adapt it if you want something slightly different.
z[] = lapply(z, function(col) col - min(col))
z
# x y
# 1 0 0
# 2 2 2
# 3 3 4
# 4 5 5
As a side note, as.data.frame(cbind(x, y)) is bad - if you have a mix of numeric and character values, cbind() will convert everything to character. It's shorter and better to simplify to data.frame(x, y).
Do you want
z[] <- lapply(z, function(columnValues) columnValues + abs(min(columnValues)))
This is my first question, so please let me know if I made any mistakes in the ask.
I am trying to create a dataframe which has multiple columns all containing the same values in the same order, but shifted in position. Where the first value from each column is moved to the end, and everything else is shifted up.
For example, I would like to convert a data frame like this:
example = data.frame(x=c(1,2,3,4), y=c(1,2,3,4), z=c(1,2,3,4), w=c(1,2,3,4)
Which looks like this
x y z w
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
into this:
x y z w
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
In the new dataframe, the "peak" or # 4 has moved progressively up in rows.
I've seen advice on how to shift columns up and down, but just replacing the remaining values with zeroes or NA. But I don't know how to shift the column up and replace the bottom-most value with what was formerly at the top.
Thanks in advance for any help.
In base R, we can update with Map by removing the sequence of elements while appending values from the end
example[-1] <- Map(function(x, y) c(tail(x, -y),
head(x, y)), example[-1], head(seq_along(example), -1))
example
# x y z w
#1 1 2 3 4
#2 2 3 4 1
#3 3 4 1 2
#4 4 1 2 3
Or another option is embed
example[] <- embed(unlist(example), 4)[1:4, 4:1]
I have two data frames as below:
> d1
v x y
1 X 1 5
2 X 2 6
3 X 3 7
4 X 4 8
> d2
v x y
1 X 1 5
2 X 2 6
3 X 3 7
4 X 4 8
I want to merge them and sum each x and y. Below command works fine for me:
> ddply(merge(d1,d2, all=TRUE), .(v), summarise, x=sum(x), y=sum(y))
v x y
1 X 10 26
In above command, I have to specify the column name for x and y. I am looking for a way to calculate the sum value with specifying each column name. Because I have a data frame which includes more than twenty columns, I don't want to specify each of them. Is there an automatical way for me to calculate all columns?
I am interested in the diversity of responses in Column B, within each category defined in Column A.
I can extract this data easily enough, I am however struggling to find a way to place it into a new column.
My data currently looks like:
A B 1 X
1 X
1 Z
1 Z
2 X
2 Y
2 Z
2 Z
2 Z
3 X
3 X
3 X
4 Y
4 Z
The code I am currently using to define the diversity follows:
df %>% count(A, B) %>% summarize(B.diversity = n())
This returns information on the diversity that I want, noting the number of different responses within each category in Column A.
However I want to populate Column C with that information per category, as follows:A B C 1 X 2
1 X 2
1 Z 2
1 Z 2
2 X 3
2 Y 3
2 Z 3
2 Z 3
2 Z 3
3 X 1
3 X 1
3 X 1
4 Y 2
4 Z 2
Does anyone know of an efficient way to go about this?