Другим подходом было бы использование односторонней связи MPI (например, http://www.linux-mag.com/id/1793). Обратите внимание, однако, что выполнение пассивных сообщений, которые вы действительно хотите здесь, довольно сложно (хотя попарно, с mpi_win_post и mpi_win_start проще), и что односторонний материал, мы надеемся, все изменится в MPI-3, я знаю, как далеко по той дороге я бы посоветовал тебе идти.
Более непосредственно связано с тем, что вы в первую очередь пытаетесь здесь, вместо того, чтобы отменять сообщения (что, как было предложено выше, довольно резкое), вероятно, гораздо проще просто пройти через все сообщения в очереди (MPI гарантирует, что сообщения не будут обгонять друг друга - единственный нюанс, если вы используете MPI_THREAD_MULTIPLE и имеющие несколько потоков отправки в пределах одной задачи MPI, в этом случае порядок porly определена):
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
void compute() {
const int maxusecs=500;
unsigned long sleepytime=(unsigned long)round(((float)rand()/RAND_MAX)*maxusecs);
usleep(sleepytime);
}
int main(int argc, char** argv)
{
int rank, size, i;
int otherrank;
const int niters=10;
const int tag=5;
double newval;
double sentvals[niters+1];
double othernewval;
MPI_Request reqs[niters+1];
MPI_Status stat;
int ready;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size != 2) {
fprintf(stderr,"This assumes 2 processes\n");
MPI_Finalize();
exit(-1);
}
otherrank = (rank == 0 ? 1 : 0);
srand(rank);
compute();
newval = rank * 100. + 0;
sentvals[0] = newval;
MPI_Isend(&(sentvals[0]), 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &(reqs[0]));
MPI_Recv (&othernewval, 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &stat);
for (i=0; i<niters; i++) {
MPI_Iprobe(otherrank, tag, MPI_COMM_WORLD, &ready, &stat);
while (ready) {
MPI_Recv(&othernewval, 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &stat);
printf("%s[%d]: Reading queued data %lf:\n",
(rank == 0 ? "" : "\t\t\t\t"), rank, othernewval);
MPI_Iprobe(otherrank, tag, MPI_COMM_WORLD, &ready, &stat);
}
printf("%s[%d]: Got data %lf, computing:\n",
(rank == 0 ? "" : "\t\t\t\t"), rank, othernewval);
compute();
/* update my data */
newval = rank * 100. + i + 1;
printf("%s[%d]: computed %lf, sending:\n",
(rank == 0 ? "" : "\t\t\t\t"), rank, newval);
sentvals[i+1] = newval;
MPI_Isend(&(sentvals[i+1]), 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &(reqs[0]));
}
MPI_Finalize();
return 0;
}
Бег это дает вам (заметьте, что только потому, что данные передаются не означает его получение во время печати):
[0]: Got data 100.000000, computing:
[1]: Got data 0.000000, computing:
[0]: computed 1.000000, sending:
[0]: Got data 100.000000, computing:
[1]: computed 101.000000, sending:
[1]: Got data 0.000000, computing:
[0]: computed 2.000000, sending:
[0]: Got data 100.000000, computing:
[1]: computed 102.000000, sending:
[1]: Reading queued data 1.000000:
[1]: Got data 1.000000, computing:
[0]: computed 3.000000, sending:
[0]: Reading queued data 101.000000:
[0]: Got data 101.000000, computing:
[1]: computed 103.000000, sending:
[1]: Reading queued data 2.000000:
[1]: Got data 2.000000, computing:
[0]: computed 4.000000, sending:
[1]: computed 104.000000, sending:
[0]: Reading queued data 102.000000:
[1]: Reading queued data 3.000000:
[1]: Got data 3.000000, computing:
[0]: Got data 102.000000, computing:
[0]: computed 5.000000, sending:
[0]: Reading queued data 103.000000:
[0]: Got data 103.000000, computing:
[1]: computed 105.000000, sending:
[1]: Reading queued data 4.000000:
[1]: Got data 4.000000, computing:
[0]: computed 6.000000, sending:
[0]: Reading queued data 104.000000:
[0]: Got data 104.000000, computing:
[1]: computed 106.000000, sending:
[1]: Reading queued data 5.000000:
[1]: Got data 5.000000, computing:
[0]: computed 7.000000, sending:
[0]: Reading queued data 105.000000:
[0]: Got data 105.000000, computing:
[1]: computed 107.000000, sending:
[1]: Reading queued data 6.000000:
[1]: Got data 6.000000, computing:
[0]: computed 8.000000, sending:
[0]: Reading queued data 106.000000:
[0]: Got data 106.000000, computing:
[1]: computed 108.000000, sending:
[1]: Reading queued data 7.000000:
[1]: Got data 7.000000, computing:
[0]: computed 9.000000, sending:
[0]: Reading queued data 107.000000:
[0]: Got data 107.000000, computing:
[1]: computed 109.000000, sending:
[1]: Reading queued data 8.000000:
[1]: Got data 8.000000, computing:
[0]: computed 10.000000, sending:
[1]: computed 110.000000, sending:
Обратите внимание, что это всего лишь демонстрационный код, окончательная версия действительно необходимо сделать waitalls и больше iprobes в конце, чтобы освободить любые ожидающие запросы и сбросить любые ожидающие сообщения.
Отмена отправки - это зло, и вы не должны его использовать. И нет никакой гарантии, что вы действительно можете отменить отправку. Если вы считаете, что можете отказаться от письменного извещения удаленно с отменой, вы будете разочарованы. – Jeff