Loading examples/00_mpi_first_steps/000_MPI_template.c 0 → 100644 +79 −0 Changes for examples/00_mpi_first_steps/000_MPI_template.c: 79 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #if defined(__STDC__) # if (__STDC_VERSION__ >= 199901L) # define _XOPEN_SOURCE 700 # endif #endif #include <stdlib.h> #include <stdio.h> #include <omp.h> #include <mpi.h> int main( int argc, char **argv ) { // ···················· // initialize MPI { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided); if ( provided < MPI_THREAD_FUNNELED ) { // manage with some meaningful message // free every memory block that you may // already allocated MPI_Abort(MPI_COMM_WORLD, 1); } } // ···················· // Best practice: don't use the // default MPI_COMM_WORLD, // use your own world int Myrank, Ntasks; MPI_Comm myCOMM_WORLD; MPI_Comm_dup ( MPI_COMM_WORLD, &myCOMM_WORLD ); // get infos on your world MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); // ····················· /* * your code */ // ···················· // always finalize MPI MPI_Finalize(); return 0; } examples/00_mpi_first_steps/000_where_I_am.c 0 → 100644 +168 −0 Changes for examples/00_mpi_first_steps/000_where_I_am.c: 168 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #if defined(__STDC__) # if (__STDC_VERSION__ >= 199901L) # define _XOPEN_SOURCE 700 # endif #endif #define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #if defined(_GNU_SOURCE) #include <sched.h> #endif #include <omp.h> #include <mpi.h> int read_proc__self_stat ( int, int * ); int get_cpu_id ( void ); int main( int argc, char **argv ) { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided); if ( provided < MPI_THREAD_FUNNELED ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } int Myrank, Ntasks; MPI_Comm myCOMM_WORLD; MPI_Comm_dup ( MPI_COMM_WORLD, &myCOMM_WORLD ); MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); int hostname_len; char myhostname[MPI_MAX_PROCESSOR_NAME]; MPI_Get_processor_name(myhostname, &hostname_len); #pragma omp parallel { #if defined (_OPENMP) int me = omp_get_thread_num(); #else int me = 0; #endif int mycpu = get_cpu_id(); printf("T %03d th %03d cpu %03d on host %s\n", Myrank, me, mycpu, myhostname); } MPI_Finalize(); return 0; } #define CPU_ID_ENTRY_IN_PROCSTAT 39 int get_cpu_id( void ) { #if defined(_GNU_SOURCE) // GNU SOURCE ------------ return sched_getcpu( ); #else #ifdef SYS_getcpu // direct sys call --- int cpuid; if ( syscall( SYS_getcpu, &cpuid, NULL, NULL ) == -1 ) return -1; else return cpuid; #else unsigned val; if ( read_proc__self_stat( CPU_ID_ENTRY_IN_PROCSTAT, &val ) == -1 ) return -1; return (int)val; #endif // ----------------------- #endif } int read_proc__self_stat( int field, int *ret_val ) /* Other interesting fields: pid : 0 father : 1 utime : 13 cutime : 14 nthreads : 18 rss : 22 cpuid : 39 read man /proc page for fully detailed infos */ { // not used, just mnemonic // char *table[ 52 ] = { [0]="pid", [1]="father", [13]="utime", [14]="cutime", [18]="nthreads", [22]="rss", [38]="cpuid"}; *ret_val = 0; FILE *file = fopen( "/proc/self/stat", "r" ); if (file == NULL ) return -1; char *line = NULL; int ret; size_t len; ret = getline( &line, &len, file ); fclose(file); if( ret == -1 ) return -1; char *savetoken = line; char *token = strtok_r( line, " ", &savetoken); --field; do { token = strtok_r( NULL, " ", &savetoken); field--; } while( field ); *ret_val = atoi(token); free(line); return 0; } examples/00_mpi_first_steps/00_basic.c 0 → 100644 +65 −0 Changes for examples/00_mpi_first_steps/00_basic.c: 65 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #include <stdlib.h> #include <stdio.h> #include <mpi.h> int main ( int argc, char **argv ) { int Rank; int Ntasks; { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided); if ( provided < MPI_THREAD_SINGLE ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } } MPI_Comm_rank( MPI_COMM_WORLD, &Rank ); MPI_Comm_size( MPI_COMM_WORLD, &Ntasks ); int planets; int myplanets; planets = (argc > 1? atoi(*(argv+1)) : 0 ); myplanets = planets / Ntasks; myplanets += (Rank < planets % Ntasks); printf( "Hello world, I'm task %d among %d friends, i'll model %d planets\n", Rank, Ntasks, myplanets ); MPI_Finalize(); return 0; } examples/00_mpi_first_steps/00_helloworld.c 0 → 100644 +71 −0 Changes for examples/00_mpi_first_steps/00_helloworld.c: 71 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ /* * Hello World example with MPI */ #include <stdlib.h> #include <stdio.h> #include <mpi.h> int main ( int argc, char **argv ) { // ················· // intialize MPI int provided_thread_level; MPI_Comm myCOMM_WORLD; MPI_Init_thread( &argc, &argv, MPI_THREAD_SINGLE, &provided_thread_level ); if ( provided_thread_level < MPI_THREAD_SINGLE ) { printf("it was impossibile to get the thread level MPI_THREAD_SINGLE\n"); MPI_Abort(MPI_COMM_WORLD, 1); } // ·················· // Good practice: don't use // MPI_COMM_WORLD // Create a separate working space int Ntasks; int Myrank; MPI_Comm_dup( MPI_COMM_WORLD, &myCOMM_WORLD ); MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); // ················· // Greetings printf("hello MPI world, I'm rank %d out of %d\n", Myrank, Ntasks ); // ················· // Finalize MPI MPI_Finalize(); return 0; } examples/01_mpi_send_receive/.backups/01_send_and_recv.c~ 0 → 100644 +105 −0 Changes for examples/01_mpi_send_receive/.backups/01_send_and_recv.c~: 105 added lines, 0 removed lines. Original line number Diff line number Diff line /* * Simple demonstration of Send and Recv * ·········································· * * Even Ranks send a message to subsequent odd ranks, * and receive a reply * */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <mpi.h> int main ( int argc, char **argv ) { // ············································ // initialize MPI int Rank; int Ntasks; { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided); if ( provided < MPI_THREAD_SINGLE ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } } MPI_Comm_rank( MPI_COMM_WORLD, &Rank ); MPI_Comm_size( MPI_COMM_WORLD, &Ntasks ); // ············································ // print the hostname for every rank char hostname[100]; int hostname_size = 100; gethostname( &hostname[0], hostname_size ); printf( "Rank %d is running on host %s\n", Rank, hostname ); MPI_Barrier(MPI_COMM_WORLD); // ············································ // determines who's my buddy int Im_even = (Rank % 2 == 0); int my_buddy; if ( Im_even ) my_buddy = Rank+1; else my_buddy = Rank-1; // ············································ // if I do have a buddy.. if ( my_buddy < Ntasks ) { #define FIRST_ROUND 0 #define SECOND_ROUND 1 if ( Im_even ) { int buddy_rank; MPI_Status status; MPI_Send( &Rank, 1, MPI_INT, my_buddy, FIRST_ROUND, MPI_COMM_WORLD ); MPI_Recv( &buddy_rank, 1, MPI_INT, my_buddy, SECOND_ROUND, MPI_COMM_WORLD, &status ); if ( status.MPI_SOURCE == my_buddy ) printf("\tRank %d says: I confirm I have received a reply from my buddy\n", Rank); else printf("oops, a stranger has replied to me\n"); } else { int buddy_rank; MPI_Status status; MPI_Recv( &buddy_rank, 1, MPI_INT, my_buddy, FIRST_ROUND, MPI_COMM_WORLD, &status ); MPI_Send( &Rank, 1, MPI_INT, my_buddy, SECOND_ROUND, MPI_COMM_WORLD ); if ( status.MPI_SOURCE == my_buddy ) printf("Rank %d says: I confirm I have received the message from my buddy\n", Rank); else printf("oops, a stranger has communicated with me\n"); } } else // ······················· // sadness printf("Rank %d has got nobody to talk with\n", Rank ); MPI_Finalize(); return 0; } Loading
examples/00_mpi_first_steps/000_MPI_template.c 0 → 100644 +79 −0 Changes for examples/00_mpi_first_steps/000_MPI_template.c: 79 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #if defined(__STDC__) # if (__STDC_VERSION__ >= 199901L) # define _XOPEN_SOURCE 700 # endif #endif #include <stdlib.h> #include <stdio.h> #include <omp.h> #include <mpi.h> int main( int argc, char **argv ) { // ···················· // initialize MPI { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided); if ( provided < MPI_THREAD_FUNNELED ) { // manage with some meaningful message // free every memory block that you may // already allocated MPI_Abort(MPI_COMM_WORLD, 1); } } // ···················· // Best practice: don't use the // default MPI_COMM_WORLD, // use your own world int Myrank, Ntasks; MPI_Comm myCOMM_WORLD; MPI_Comm_dup ( MPI_COMM_WORLD, &myCOMM_WORLD ); // get infos on your world MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); // ····················· /* * your code */ // ···················· // always finalize MPI MPI_Finalize(); return 0; }
examples/00_mpi_first_steps/000_where_I_am.c 0 → 100644 +168 −0 Changes for examples/00_mpi_first_steps/000_where_I_am.c: 168 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #if defined(__STDC__) # if (__STDC_VERSION__ >= 199901L) # define _XOPEN_SOURCE 700 # endif #endif #define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #if defined(_GNU_SOURCE) #include <sched.h> #endif #include <omp.h> #include <mpi.h> int read_proc__self_stat ( int, int * ); int get_cpu_id ( void ); int main( int argc, char **argv ) { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided); if ( provided < MPI_THREAD_FUNNELED ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } int Myrank, Ntasks; MPI_Comm myCOMM_WORLD; MPI_Comm_dup ( MPI_COMM_WORLD, &myCOMM_WORLD ); MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); int hostname_len; char myhostname[MPI_MAX_PROCESSOR_NAME]; MPI_Get_processor_name(myhostname, &hostname_len); #pragma omp parallel { #if defined (_OPENMP) int me = omp_get_thread_num(); #else int me = 0; #endif int mycpu = get_cpu_id(); printf("T %03d th %03d cpu %03d on host %s\n", Myrank, me, mycpu, myhostname); } MPI_Finalize(); return 0; } #define CPU_ID_ENTRY_IN_PROCSTAT 39 int get_cpu_id( void ) { #if defined(_GNU_SOURCE) // GNU SOURCE ------------ return sched_getcpu( ); #else #ifdef SYS_getcpu // direct sys call --- int cpuid; if ( syscall( SYS_getcpu, &cpuid, NULL, NULL ) == -1 ) return -1; else return cpuid; #else unsigned val; if ( read_proc__self_stat( CPU_ID_ENTRY_IN_PROCSTAT, &val ) == -1 ) return -1; return (int)val; #endif // ----------------------- #endif } int read_proc__self_stat( int field, int *ret_val ) /* Other interesting fields: pid : 0 father : 1 utime : 13 cutime : 14 nthreads : 18 rss : 22 cpuid : 39 read man /proc page for fully detailed infos */ { // not used, just mnemonic // char *table[ 52 ] = { [0]="pid", [1]="father", [13]="utime", [14]="cutime", [18]="nthreads", [22]="rss", [38]="cpuid"}; *ret_val = 0; FILE *file = fopen( "/proc/self/stat", "r" ); if (file == NULL ) return -1; char *line = NULL; int ret; size_t len; ret = getline( &line, &len, file ); fclose(file); if( ret == -1 ) return -1; char *savetoken = line; char *token = strtok_r( line, " ", &savetoken); --field; do { token = strtok_r( NULL, " ", &savetoken); field--; } while( field ); *ret_val = atoi(token); free(line); return 0; }
examples/00_mpi_first_steps/00_basic.c 0 → 100644 +65 −0 Changes for examples/00_mpi_first_steps/00_basic.c: 65 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ #include <stdlib.h> #include <stdio.h> #include <mpi.h> int main ( int argc, char **argv ) { int Rank; int Ntasks; { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided); if ( provided < MPI_THREAD_SINGLE ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } } MPI_Comm_rank( MPI_COMM_WORLD, &Rank ); MPI_Comm_size( MPI_COMM_WORLD, &Ntasks ); int planets; int myplanets; planets = (argc > 1? atoi(*(argv+1)) : 0 ); myplanets = planets / Ntasks; myplanets += (Rank < planets % Ntasks); printf( "Hello world, I'm task %d among %d friends, i'll model %d planets\n", Rank, Ntasks, myplanets ); MPI_Finalize(); return 0; }
examples/00_mpi_first_steps/00_helloworld.c 0 → 100644 +71 −0 Changes for examples/00_mpi_first_steps/00_helloworld.c: 71 added lines, 0 removed lines. Original line number Diff line number Diff line /* ────────────────────────────────────────────────────────────────────────── * │ │ │ This file is part of the exercises for the Lectures on │ │ "Foundations of High Performance Computing" │ │ given at │ │ Master in HPC and │ │ Master in Data Science and Scientific Computing │ │ @ SISSA, ICTP and University of Trieste │ │ │ │ contact: luca.tornatore@inaf.it │ │ │ │ This is free software; you can redistribute it and/or modify │ │ it under the terms of the GNU General Public License as published by │ │ the Free Software Foundation; either version 3 of the License, or │ │ (at your option) any later version. │ │ This code is distributed in the hope that it will be useful, │ │ but WITHOUT ANY WARRANTY; without even the implied warranty of │ │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the │ │ GNU General Public License for more details. │ │ │ │ You should have received a copy of the GNU General Public License │ │ along with this program. If not, see <http://www.gnu.org/licenses/> │ │ │ * ────────────────────────────────────────────────────────────────────────── */ /* * Hello World example with MPI */ #include <stdlib.h> #include <stdio.h> #include <mpi.h> int main ( int argc, char **argv ) { // ················· // intialize MPI int provided_thread_level; MPI_Comm myCOMM_WORLD; MPI_Init_thread( &argc, &argv, MPI_THREAD_SINGLE, &provided_thread_level ); if ( provided_thread_level < MPI_THREAD_SINGLE ) { printf("it was impossibile to get the thread level MPI_THREAD_SINGLE\n"); MPI_Abort(MPI_COMM_WORLD, 1); } // ·················· // Good practice: don't use // MPI_COMM_WORLD // Create a separate working space int Ntasks; int Myrank; MPI_Comm_dup( MPI_COMM_WORLD, &myCOMM_WORLD ); MPI_Comm_size( myCOMM_WORLD, &Ntasks ); MPI_Comm_rank( myCOMM_WORLD, &Myrank ); // ················· // Greetings printf("hello MPI world, I'm rank %d out of %d\n", Myrank, Ntasks ); // ················· // Finalize MPI MPI_Finalize(); return 0; }
examples/01_mpi_send_receive/.backups/01_send_and_recv.c~ 0 → 100644 +105 −0 Changes for examples/01_mpi_send_receive/.backups/01_send_and_recv.c~: 105 added lines, 0 removed lines. Original line number Diff line number Diff line /* * Simple demonstration of Send and Recv * ·········································· * * Even Ranks send a message to subsequent odd ranks, * and receive a reply * */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <mpi.h> int main ( int argc, char **argv ) { // ············································ // initialize MPI int Rank; int Ntasks; { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided); if ( provided < MPI_THREAD_SINGLE ) { // manage MPI_Abort(MPI_COMM_WORLD, 1); } } MPI_Comm_rank( MPI_COMM_WORLD, &Rank ); MPI_Comm_size( MPI_COMM_WORLD, &Ntasks ); // ············································ // print the hostname for every rank char hostname[100]; int hostname_size = 100; gethostname( &hostname[0], hostname_size ); printf( "Rank %d is running on host %s\n", Rank, hostname ); MPI_Barrier(MPI_COMM_WORLD); // ············································ // determines who's my buddy int Im_even = (Rank % 2 == 0); int my_buddy; if ( Im_even ) my_buddy = Rank+1; else my_buddy = Rank-1; // ············································ // if I do have a buddy.. if ( my_buddy < Ntasks ) { #define FIRST_ROUND 0 #define SECOND_ROUND 1 if ( Im_even ) { int buddy_rank; MPI_Status status; MPI_Send( &Rank, 1, MPI_INT, my_buddy, FIRST_ROUND, MPI_COMM_WORLD ); MPI_Recv( &buddy_rank, 1, MPI_INT, my_buddy, SECOND_ROUND, MPI_COMM_WORLD, &status ); if ( status.MPI_SOURCE == my_buddy ) printf("\tRank %d says: I confirm I have received a reply from my buddy\n", Rank); else printf("oops, a stranger has replied to me\n"); } else { int buddy_rank; MPI_Status status; MPI_Recv( &buddy_rank, 1, MPI_INT, my_buddy, FIRST_ROUND, MPI_COMM_WORLD, &status ); MPI_Send( &Rank, 1, MPI_INT, my_buddy, SECOND_ROUND, MPI_COMM_WORLD ); if ( status.MPI_SOURCE == my_buddy ) printf("Rank %d says: I confirm I have received the message from my buddy\n", Rank); else printf("oops, a stranger has communicated with me\n"); } } else // ······················· // sadness printf("Rank %d has got nobody to talk with\n", Rank ); MPI_Finalize(); return 0; }