При использовании разделяемой памяти MPI 3 мне пришло в голову, что запись в смежные позиции памяти окна совместно используемой памяти одновременно для разных задач, по-видимому, не работает.
Я догадывался, что MPI игнорирует возможные конфликты кэша, и теперь У меня вопрос: верно ли это, и MPI действительно не заботится о когерентности кэша, или это извращенная реализация, или есть ли совершенно другое объяснение этому поведению?
Это минимальный пример где в Фортране одновременная запись по разным адресам в окне общей памяти вызывает конфликт (протестировано с Intel MPI 2017, 2018, 2019 и GNU OpenMPI 3).
program testAlloc
use mpi
use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_f_pointer
implicit none
integer :: ierr
integer :: window
integer(kind=MPI_Address_kind) :: wsize
type(c_ptr) :: baseptr
integer, pointer :: f_ptr
integer :: comm_rank
call MPI_Init(ierr)
! Each processor allocates one entry
wsize = 1
call MPI_WIN_ALLOCATE_SHARED(wsize,4,MPI_INFO_NULL,MPI_COMM_WORLD,baseptr,window,ierr)
! Convert to a fortran pointer
call c_f_pointer(baseptr, f_ptr)
! Now, assign some value simultaneously
f_ptr = 4
! For output, get the mpi rank
call mpi_comm_rank(MPI_COMM_WORLD, comm_rank, ierr)
! Output the assigned value - only one task reports 4, the others report junk
print *, "On task", comm_rank, "value is", f_ptr
call MPI_Win_free(window, ierr)
call MPI_Finalize(ierr)
end program
Любопытно, что одна и та же программа в C, кажется, работает как задумано, что приводит к вопросу, если что-то не так с реализацией на Фортране, или программе C просто повезло (протестировано с теми же библиотеками MPI)
#include <mpi.h>
#include <stdio.h>
int main(int argc, char *argv[]){
MPI_Init(&argc, &argv);
// Allocate a single resource per task
MPI_Aint wsize = 1;
// Do a shared allocation
int *resource;
MPI_Win window;
MPI_Win_allocate_shared(wsize, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &resource, &window);
// For output clarification, get the mpi rank
int comm_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
// Assign some value
*resource = 4;
// Tell us the value - this seems to work
printf("On task %d the value is %d\n",comm_rank,*resource);
MPI_Win_free(&window);
MPI_Finalize();
}