Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add MPI_Win_get_name and MPI_Win_set_name support
[simgrid.git] / src / smpi / smpi_rma.c
1
2 /* Copyright (c) 2007-2014. The SimGrid Team.
3  * All rights reserved.                                                     */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "private.h"
9
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_rma, smpi, "Logging specific to SMPI (RMA operations)");
11
12 #define RMA_TAG -1234
13
14 xbt_bar_t creation_bar = NULL;
15
16 typedef struct s_smpi_mpi_win{
17   void* base;
18   MPI_Aint size;
19   int disp_unit;
20   MPI_Comm comm;
21   //MPI_Info info
22   int assert;
23   xbt_dynar_t requests;
24   xbt_bar_t bar;
25   MPI_Win* connected_wins;
26   char* name;
27 } s_smpi_mpi_win_t;
28
29
30 MPI_Win smpi_mpi_win_create( void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm){
31
32   MPI_Win win;
33   
34   int comm_size = smpi_comm_size(comm);
35   int rank=smpi_comm_rank(comm);
36   XBT_DEBUG("Creating window");
37
38   win = xbt_new(s_smpi_mpi_win_t, 1);
39   win->base = base;
40   win->size = size;
41   win->disp_unit = disp_unit;
42   win->assert = 0;
43   //win->info = info;
44   win->comm = comm;
45   win->name = NULL;
46   win->requests = xbt_dynar_new(sizeof(MPI_Request), NULL);
47   win->connected_wins = xbt_malloc0(comm_size*sizeof(MPI_Win));
48   win->connected_wins[rank] = win;
49   
50   if(rank==0){
51     win->bar=xbt_barrier_init(comm_size);
52   }
53   
54   mpi_coll_allgather_fun(&(win->connected_wins[rank]),
55                      sizeof(MPI_Win),
56                      MPI_BYTE,
57                      win->connected_wins,
58                      sizeof(MPI_Win),
59                      MPI_BYTE,
60                      comm);
61                      
62   mpi_coll_bcast_fun( &(win->bar),
63                      sizeof(xbt_bar_t),
64                      MPI_BYTE,
65                      0,
66                      comm);
67                      
68   mpi_coll_barrier_fun(comm);
69   
70   return win;
71 }
72
73 int smpi_mpi_win_free( MPI_Win* win){
74
75   //As per the standard, perform a barrier to ensure every async comm is finished
76   xbt_barrier_wait((*win)->bar);
77   xbt_dynar_free(&(*win)->requests);
78   xbt_free((*win)->connected_wins);
79   if ((*win)->name != NULL){
80     xbt_free((*win)->name);
81   }
82   xbt_free(*win);
83   win = MPI_WIN_NULL;
84   return MPI_SUCCESS;
85 }
86
87 void smpi_mpi_win_get_name(MPI_Win win, char* name, int* length){
88   *length = strlen(win->name);
89   strcpy(name, win->name);
90 }
91
92 void smpi_mpi_win_set_name(MPI_Win win, char* name){
93   win->name = strdup(name);;
94 }
95
96
97 int smpi_mpi_win_fence( int assert,  MPI_Win win){
98
99   XBT_DEBUG("Entering fence");
100
101   if(assert != MPI_MODE_NOPRECEDE){
102     xbt_barrier_wait(win->bar);
103
104     xbt_dynar_t reqs = win->requests;
105     int size = xbt_dynar_length(reqs);
106     unsigned int cpt=0;
107     MPI_Request req;
108     // start all requests that have been prepared by another process
109     xbt_dynar_foreach(reqs, cpt, req){
110       if (req->flags & PREPARED) smpi_mpi_start(req);
111     }
112
113     MPI_Request* treqs = xbt_dynar_to_array(reqs);
114     smpi_mpi_waitall(size,treqs,MPI_STATUSES_IGNORE);
115     xbt_free(treqs);
116     win->requests=xbt_dynar_new(sizeof(MPI_Request), NULL);
117
118   }
119   win->assert = assert;
120   
121   xbt_barrier_wait(win->bar);
122   XBT_DEBUG("Leaving fence ");
123
124   return MPI_SUCCESS;
125 }
126
127 int smpi_mpi_put( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
128               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win)
129 {
130   //get receiver pointer
131   MPI_Win recv_win = win->connected_wins[target_rank];
132
133   void* recv_addr = (void*) ( ((char*)recv_win->base) + target_disp * recv_win->disp_unit);
134   smpi_datatype_use(origin_datatype);
135   smpi_datatype_use(target_datatype);
136   XBT_DEBUG("Entering MPI_Put to %d", target_rank);
137
138   if(target_rank != smpi_comm_rank(win->comm)){
139     //prepare send_request
140     MPI_Request sreq = smpi_rma_send_init(origin_addr, origin_count, origin_datatype,
141         smpi_process_index(), smpi_group_index(smpi_comm_group(win->comm),target_rank), RMA_TAG+1, win->comm, MPI_OP_NULL);
142
143     //prepare receiver request
144     MPI_Request rreq = smpi_rma_recv_init(recv_addr, target_count, target_datatype,
145         smpi_process_index(), smpi_group_index(smpi_comm_group(win->comm),target_rank), RMA_TAG+1, recv_win->comm, MPI_OP_NULL);
146
147     //push request to receiver's win
148     xbt_dynar_push_as(recv_win->requests, MPI_Request, rreq);
149
150     //start send
151     smpi_mpi_start(sreq);
152
153     //push request to sender's win
154     xbt_dynar_push_as(win->requests, MPI_Request, sreq);
155   }else{
156     smpi_datatype_copy(origin_addr, origin_count, origin_datatype,
157                        recv_addr, target_count, target_datatype);
158   }
159
160   return MPI_SUCCESS;
161 }
162
163 int smpi_mpi_get( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
164               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win)
165 {
166   //get sender pointer
167   MPI_Win send_win = win->connected_wins[target_rank];
168
169   void* send_addr = (void*)( ((char*)send_win->base) + target_disp * send_win->disp_unit);
170   smpi_datatype_use(origin_datatype);
171   smpi_datatype_use(target_datatype);
172   XBT_DEBUG("Entering MPI_Get from %d", target_rank);
173
174   if(target_rank != smpi_comm_rank(win->comm)){
175     //prepare send_request
176     MPI_Request sreq = smpi_rma_send_init(send_addr, target_count, target_datatype,
177         smpi_group_index(smpi_comm_group(win->comm),target_rank), smpi_process_index(), RMA_TAG+2, send_win->comm, MPI_OP_NULL);
178
179     //prepare receiver request
180     MPI_Request rreq = smpi_rma_recv_init(origin_addr, origin_count, origin_datatype,
181         smpi_group_index(smpi_comm_group(win->comm),target_rank), smpi_process_index(), RMA_TAG+2, win->comm, MPI_OP_NULL);
182         
183     //start the send, with another process than us as sender. 
184     smpi_mpi_start(sreq);
185     
186     //push request to receiver's win
187     xbt_dynar_push_as(send_win->requests, MPI_Request, sreq);
188
189     //start recv
190     smpi_mpi_start(rreq);
191
192     //push request to sender's win
193     xbt_dynar_push_as(win->requests, MPI_Request, rreq);
194   }else{
195     smpi_datatype_copy(send_addr, target_count, target_datatype,
196                        origin_addr, origin_count, origin_datatype);
197   }
198
199   return MPI_SUCCESS;
200 }
201
202
203 int smpi_mpi_accumulate( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
204               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win)
205 {
206   //FIXME: local version 
207   //get receiver pointer
208   MPI_Win recv_win = win->connected_wins[target_rank];
209
210   void* recv_addr = (void*)( ((char*)recv_win->base) + target_disp * recv_win->disp_unit);
211   XBT_DEBUG("Entering MPI_Accumulate to %d", target_rank);
212
213   smpi_datatype_use(origin_datatype);
214   smpi_datatype_use(target_datatype);
215
216
217     //prepare send_request
218     MPI_Request sreq = smpi_rma_send_init(origin_addr, origin_count, origin_datatype,
219         smpi_process_index(), smpi_group_index(smpi_comm_group(win->comm),target_rank), RMA_TAG+3, win->comm, op);
220
221     //prepare receiver request
222     MPI_Request rreq = smpi_rma_recv_init(recv_addr, target_count, target_datatype,
223         smpi_process_index(), smpi_group_index(smpi_comm_group(win->comm),target_rank), RMA_TAG+3, recv_win->comm, op);
224     //push request to receiver's win
225     xbt_dynar_push_as(recv_win->requests, MPI_Request, rreq);
226     //start send
227     smpi_mpi_start(sreq);
228     
229     //push request to sender's win
230     xbt_dynar_push_as(win->requests, MPI_Request, sreq);
231   
232
233
234   return MPI_SUCCESS;
235 }
236