I am trying to write an MPI function in C++ that takes only those elements in a vector that satisfy some condition and outputs them to another vector. The input sequence must be evenly distributed across all processors as does the output sequence. The function takes MPI_Comm comm
,std::vector<T>& in
, std::vector<T>& out
, and Pred pred
as parameters. I'm not quite sure the best approach to take.
Asked
Active
Viewed 108 times
0
1 Answers
0
You need to form a buffer and fill the buffer based on your condition. Then based on what kind of transfers you want, you can either use, the blocking/non-blocking versions of MPI_Send
/MPI_Isend
and MPI_Recv
/MPI_Irecv
between the ranks of the comm
that you pass in.
If you want more information, you would need to provide more information on what exactly you want to achieve. Is the input and output vectors already distributed across the ranks ? Or are the input and output vectors the input and output of the function. What exactly is pred
? Do you expect all ranks to call this function ? What does your condition depend on ?
Update:
#include <vector>
#include <mpi.h>
template <typename T, typename Pred>
void mpi_extract_if(MPI_Comm comm, const std::vector<T>& in, std::vector<T>& out, Pred pred)
{
int x = MPI_Comm_size(comm, &x);
//Use pred to fill a buffer
auto *buf;
pred(&in,&buf);
// Fill with appropriate sizes, vectors and buffers.
MPI_Scatterv(const void *sendbuf, const int *sendcounts, const int *displs,
MPI_Datatype sendtype, void *out, int recvcount,
MPI_Datatype recvtype,
int root, MPI_Comm comm);
//MPI_Scatter(in.data(), x/in.size(), MPI_BYTE, out, x/in.size(), MPI_BYTE, 0, comm);
}

Mathnoob
- 27
- 7
-
The input and output vectors are passed to the function from main. Input is already populated and is has length n*p so that each processor stores n elements. Pred returns true if for each element in the input array that is a prime number and this is the condition. All ranks should call this function. Up until this point I have yet to see MPI functions implemented outside of main and this is what I'm having a hard time with. – d_iggs17 Nov 18 '18 at 15:16
-
This is what I have so far. My apologies for the formatting `#include
#include – d_iggs17 Nov 18 '18 at 16:29template void mpi_extract_if(MPI_Comm comm, const std::vector & in, std::vector & out, Pred pred) { int x = MPI_Comm_size(comm, &x); MPI_Scatter(in.data(), x/in.size(), MPI_BYTE, out, x/in.size(), MPI_BYTE, 0, comm); }` -
Okay, I see. So, if what kind of behaviour do you want in case your `pred` returns `false`. I am guessing you dont want that element of the `in` vector to be sent. In this case, I dont think you can use `MPI_Scatter` directly on your `in` vector. What you want to do is using your `pred`, process your `in` array into a buffer. Then you can send them to the processes you need. You could use `MPI_Scatterv` if the number of elements vary or use MPI point to point if you need finer control and are sending complex data to only a few processes. – Mathnoob Nov 18 '18 at 16:51
-
Does this look right? I keep getting an error when compiling, "undefined reference to main" ` int x = MPI_Comm_size(comm, &x); T buf; for (int i = 0; i < x; i++) if(pred(in[i])) MPI_Send(&buf, x/in.size(), MPI_BYTE, out, 0, comm);` – d_iggs17 Nov 18 '18 at 17:08
-
You should have a look [here](https://stackoverflow.com/questions/14620435/c-error-undefined-reference-to-main) for that. – Mathnoob Nov 18 '18 at 17:11
-
What is wrong with this? `int x = MPI_Comm_size(comm, &x); T buf = in; for (int i = 0; i < x; i++) if(pred(in[i])) MPI_Send(&buf, x/in.size(), MPI_BYTE, out[i], 0, comm);` – d_iggs17 Nov 18 '18 at 18:15
-
Produces the following error. I believe it's argument 4 that is tripping me up `error: cannot convert ‘std::vector
’ to ‘int’ for argument ‘4’ to ‘int MPI_Send(const void*, int, MPI_Datatype, int, int, MPI_Comm)’ if(pred(in[i])) MPI_Send(&buf, x/in.size(), MPI_BYTE, out[i], 0, comm);` – d_iggs17 Nov 18 '18 at 18:18 -
Your `buf` is s vector and you are trying to put it in an element of `out` and hence it is complaining. You either need to change it to send an element of `buf` or change `out` to be a vector of vectors depending on what you want. – Mathnoob Nov 19 '18 at 10:34
-
Now I get this `error: subscripted value is neither array nor pointer if(pred(in[i])) MPI_Send(buf[1], x/in.size(), MPI_BYTE, out[i], 0, comm);` I want to leave `out` as is and just send the elements from in. How would this look like? – d_iggs17 Nov 19 '18 at 15:40
-
If you provide your whole code, then it is probably easier to debug. With this snippet, it is hard to see what you are doing. Also, for a first instance, solve it with a toy problem. Take say 4 ranks, take a `in` vector say `1,3,4,6` or so in rank 0, and tell me what you want your `out` in the other processes to be. Do this for all the 4 ranks, then it is easier to code and check if you have got what you wanted. – Mathnoob Nov 20 '18 at 06:06