~ubuntu-branches/ubuntu/utopic/nwchem/utopic

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src/devices/mpi-spawn/mpi2_client.c

  • Committer: Package Import Robot
  • Author(s): Michael Banck, Daniel Leidert, Andreas Tille, Michael Banck
  • Date: 2013-07-04 12:14:55 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130704121455-5tvsx2qabor3nrui
Tags: 6.3-1
* New upstream release.
* Fixes anisotropic properties (Closes: #696361).
* New features include:
  + Multi-reference coupled cluster (MRCC) approaches
  + Hybrid DFT calculations with short-range HF 
  + New density-functionals including Minnesota (M08, M11) and HSE hybrid
    functionals
  + X-ray absorption spectroscopy (XAS) with TDDFT
  + Analytical gradients for the COSMO solvation model
  + Transition densities from TDDFT 
  + DFT+U and Electron-Transfer (ET) methods for plane wave calculations
  + Exploitation of space group symmetry in plane wave geometry optimizations
  + Local density of states (LDOS) collective variable added to Metadynamics
  + Various new XC functionals added for plane wave calculations, including
    hybrid and range-corrected ones
  + Electric field gradients with relativistic corrections 
  + Nudged Elastic Band optimization method
  + Updated basis sets and ECPs 

[ Daniel Leidert ]
* debian/watch: Fixed.

[ Andreas Tille ]
* debian/upstream: References

[ Michael Banck ]
* debian/upstream (Name): New field.
* debian/patches/02_makefile_flags.patch: Refreshed.
* debian/patches/06_statfs_kfreebsd.patch: Likewise.
* debian/patches/07_ga_target_force_linux.patch: Likewise.
* debian/patches/05_avoid_inline_assembler.patch: Removed, no longer needed.
* debian/patches/09_backported_6.1.1_fixes.patch: Likewise.
* debian/control (Build-Depends): Added gfortran-4.7 and gcc-4.7.
* debian/patches/10_force_gcc-4.7.patch: New patch, explicitly sets
  gfortran-4.7 and gcc-4.7, fixes test suite hang with gcc-4.8 (Closes:
  #701328, #713262).
* debian/testsuite: Added tests for COSMO analytical gradients and MRCC.
* debian/rules (MRCC_METHODS): New variable, required to enable MRCC methods.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if HAVE_CONFIG_H
 
2
#   include "config.h"
 
3
#endif
 
4
 
 
5
/**
 
6
 * MPI_SPAWN: ARMCI on top of MPI.
 
7
 * Manojkumar Krishnan
 
8
 */
 
9
 
 
10
#if HAVE_STDARG_H
 
11
#   include <stdarg.h>
 
12
#endif
 
13
#if HAVE_STDIO_H
 
14
#   include <stdio.h>
 
15
#endif
 
16
#if HAVE_STRING_H
 
17
#   include <string.h>
 
18
#endif
 
19
#if HAVE_STDLIB_H
 
20
#   include <stdlib.h>
 
21
#endif
 
22
#include "mpi.h"
 
23
 
 
24
#include "mpi2.h"
 
25
#include "armcip.h"
 
26
#include "request.h"
 
27
#include "shmem.h"
 
28
#include "locks.h"
 
29
 
 
30
#define ARMCI_ROOT 0 /* root process */
 
31
 
 
32
/* Inter-communicators for communicating between clients and data servers */
 
33
MPI_Comm MPI_COMM_CLIENT2SERVER=MPI_COMM_NULL;
 
34
 
 
35
static int armci_nserver=-1;
 
36
static int *_armci_mpi_tag=NULL;
 
37
 
 
38
extern char ***_armci_argv;
 
39
extern int armci_get_shmem_info(char *addrp,  int* shmid, long *shmoffset,
 
40
                                size_t *shmsize);
 
41
 
 
42
#if MPI_SPAWN_DEBUG
 
43
void armci_mpi2_debug(int rank, const char *format, ...) 
 
44
{
 
45
    va_list arg;
 
46
 
 
47
    if(rank == armci_me) 
 
48
    {
 
49
       va_start(arg, format);
 
50
       printf("%d: ", rank);
 
51
       vprintf(format, arg);
 
52
       va_end(arg);
 
53
       fflush(stdout);
 
54
    }    
 
55
}
 
56
#else
 
57
#define armci_mpi2_debug(x, ...)
 
58
#endif
 
59
 
 
60
#if MPI_SPAWN_DEBUG
 
61
static inline int MPI_Check (int status)
 
62
{
 
63
    if(status != MPI_SUCCESS) 
 
64
    {
 
65
       armci_mpi2_debug(armci_me, "MPI Check failed.\n");
 
66
       armci_die("MPI_Check failed.", 0);
 
67
    }
 
68
}
 
69
#else
 
70
# define MPI_Check(x) x
 
71
#endif
 
72
 
 
73
 
 
74
/**************************************************************************
 
75
 * Platform specific server code as required by the ARMCI s/w layer. (BEGIN)
 
76
 */
 
77
 
 
78
/* Create connections between clients and servers */
 
79
void armci_init_connections()
 
80
{
 
81
    armci_mpi2_debug(0, "armci_init_connections\n");
 
82
    _armci_buf_init();    /* CHECK: Is this correct ? */
 
83
}
 
84
 
 
85
void armci_wait_for_server()
 
86
{
 
87
    armci_mpi2_debug(0, "armci_wait_for_server: wait for server to quit\n");
 
88
    if (armci_me == armci_master)
 
89
    {
 
90
       armci_serv_quit();  
 
91
    }
 
92
}
 
93
 
 
94
void armci_client_connect_to_servers()
 
95
{
 
96
    armci_mpi2_debug(0, "armci_client_connect_to_servers\n");   
 
97
}
 
98
 
 
99
/* NOTE: armci_mpi_strided and armci_mpi_strided2 are the only 2 functions
 
100
 * that are common to client and server part  */
 
101
void armci_mpi_strided(int op, void *ptr, int stride_levels, int stride_arr[], 
 
102
                       int count[], int proc, MPI_Comm comm)
 
103
{
 
104
    int i, j;
 
105
    long idx;    /* index offset of current block position to ptr */
 
106
    int n1dim;  /* number of 1 dim block */
 
107
    int bvalue[MAX_STRIDE_LEVEL], bunit[MAX_STRIDE_LEVEL];
 
108
    MPI_Status status;
 
109
    
 
110
    /* number of n-element of the first dimension */
 
111
    n1dim = 1;
 
112
    for(i=1; i<=stride_levels; i++)
 
113
        n1dim *= count[i];
 
114
 
 
115
    /* calculate the destination indices */
 
116
    bvalue[0] = 0; bvalue[1] = 0; bunit[0] = 1; bunit[1] = 1;
 
117
    for(i=2; i<=stride_levels; i++)
 
118
    {
 
119
        bvalue[i] = 0;
 
120
        bunit[i] = bunit[i-1] * count[i-1];
 
121
    }
 
122
 
 
123
    for(i=0; i<n1dim; i++)
 
124
    {
 
125
        idx = 0;
 
126
        for(j=1; j<=stride_levels; j++)
 
127
        {
 
128
            idx += bvalue[j] * stride_arr[j-1];
 
129
            if((i+1) % bunit[j] == 0) bvalue[j]++;
 
130
            if(bvalue[j] > (count[j]-1)) bvalue[j] = 0;
 
131
        }
 
132
 
 
133
        if(op == SEND) 
 
134
        {
 
135
           MPI_Check(
 
136
              MPI_Send(((char*)ptr)+idx, count[0], MPI_BYTE, proc,
 
137
                       ARMCI_MPI_SPAWN_DATA_TAG, comm)
 
138
              );
 
139
        }
 
140
        else /* ( op == RECV) */
 
141
        {
 
142
           MPI_Check(
 
143
              MPI_Recv(((char*)ptr)+idx, count[0], MPI_BYTE, proc,
 
144
                       ARMCI_MPI_SPAWN_DATA_TAG, comm, &status)
 
145
              );
 
146
        }
 
147
    }
 
148
}
 
149
 
 
150
/* This is the only function that is common to client and server part */
 
151
void armci_mpi_strided2(int op, void *ptr, int stride_levels, int stride_arr[],
 
152
                        int count[], int proc, MPI_Comm comm)
 
153
{
 
154
    int i, stride=1;
 
155
    MPI_Status status;
 
156
    MPI_Datatype type[MAX_STRIDE_LEVEL];
 
157
 
 
158
    if(stride_levels == 0) 
 
159
    {
 
160
        armci_mpi_strided(op, ptr, stride_levels, stride_arr, count, proc,
 
161
                          comm);
 
162
        return;
 
163
    }
 
164
 
 
165
    /* convert stided data desciption to MPI type */
 
166
    type[0] = MPI_BYTE;
 
167
    for(i=1; i<=stride_levels; i++) 
 
168
    {
 
169
       stride *= stride_arr[i-1];
 
170
       MPI_Check( MPI_Type_hvector(count[i], count[i-1], stride,
 
171
                                  type[i-1], &type[i]) );
 
172
    }
 
173
    MPI_Check( MPI_Type_commit(&type[stride_levels]) );
 
174
    
 
175
    if(op == SEND) 
 
176
    {
 
177
       MPI_Check( MPI_Send(ptr, 1, type[stride_levels], proc,
 
178
                           ARMCI_MPI_SPAWN_VDATA_TAG, comm) );
 
179
    }
 
180
    else /* ( op == RECV) */
 
181
    {
 
182
       MPI_Check( MPI_Recv(ptr, 1, type[stride_levels], proc,
 
183
                           ARMCI_MPI_SPAWN_VDATA_TAG, comm, &status) );
 
184
    }
 
185
}
 
186
 
 
187
/*\ client sends request message to server
 
188
\*/
 
189
int armci_send_req_msg (int proc, void *buf, int bytes)
 
190
{
 
191
  int server = armci_clus_id(proc);
 
192
 
 
193
  armci_mpi2_debug(armci_me, "armci_send_req_msg(): proc=%d, server=%d, "
 
194
                   "buf=%p, bytes=%d\n", proc, server, buf, bytes);
 
195
  
 
196
  if( !(server >= 0 && server < armci_nserver) )
 
197
     armci_die("armci_send_req_msg: Invalid server.", 0);
 
198
 
 
199
#ifdef MULTIPLE_BUFS
 
200
  /**
 
201
   * Sequentially ordered tags to ensure flow control at the server side.
 
202
   * For example, a put followed by get from a client should be processed in
 
203
   * ORDER at the server side. If we don't have the flow control, the server
 
204
   * might process the get request first instead of put (and thus violating
 
205
   * ARMCI's ordering semantics.
 
206
   */
 
207
  ((request_header_t*)buf)->tag = _armci_mpi_tag[server];
 
208
  MPI_Check(
 
209
     MPI_Send(buf, bytes, MPI_BYTE, server, ARMCI_MPI_SPAWN_TAG,
 
210
              MPI_COMM_CLIENT2SERVER)
 
211
     );
 
212
 
 
213
  _armci_mpi_tag[server]++;
 
214
  if(_armci_mpi_tag[server] > ARMCI_MPI_SPAWN_TAG_END) 
 
215
     _armci_mpi_tag[server] = ARMCI_MPI_SPAWN_TAG_BEGIN;
 
216
  
 
217
#else
 
218
  MPI_Check(
 
219
     MPI_Send(buf, bytes, MPI_BYTE, server, ARMCI_MPI_SPAWN_TAG,
 
220
              MPI_COMM_CLIENT2SERVER)
 
221
     );
 
222
#endif
 
223
  armci_mpi2_debug(armci_me, "armci_send_req_msg(): send msg to server(%d), to"
 
224
                   "fwd to client %d\n", server, proc);
 
225
 
 
226
  return 0;
 
227
}
 
228
 
 
229
/*\ client sends strided data + request to server
 
230
\*/
 
231
int armci_send_req_msg_strided(int proc, request_header_t *msginfo,char *ptr,
 
232
                               int strides, int stride_arr[], int count[])
 
233
{
 
234
    int server = armci_clus_id(proc);
 
235
    int bytes;
 
236
 
 
237
    armci_mpi2_debug(armci_me, "armci_send_req_msg_strided: proc=%d server=%d "
 
238
                     "bytes=%d (op=%d)\n", proc, server, msginfo->datalen,
 
239
                     msginfo->operation);
 
240
 
 
241
    THREAD_LOCK(armci_user_threads.net_lock);
 
242
 
 
243
    /* we write header + descriptor of strided data  */
 
244
    bytes = sizeof(request_header_t) + msginfo->dscrlen;
 
245
    armci_send_req_msg(proc, msginfo, bytes);
 
246
    
 
247
#ifdef MPI_USER_DEF_DATATYPE
 
248
    if(strides>0) 
 
249
    {
 
250
       armci_mpi_strided2(SEND, ptr, strides, stride_arr, count, server,
 
251
                          MPI_COMM_CLIENT2SERVER);
 
252
    }
 
253
    else
 
254
#endif
 
255
    {
 
256
       /* for larger blocks write directly thus avoiding memcopy */
 
257
       armci_mpi_strided(SEND, ptr, strides, stride_arr, count, server,
 
258
                         MPI_COMM_CLIENT2SERVER);
 
259
    }
 
260
       
 
261
    THREAD_UNLOCK(armci_user_threads.net_lock);
 
262
 
 
263
    armci_mpi2_debug(armci_me, "armci_send_req_msg_strided(): send msg to "
 
264
                     "server(%d), to fwd to client %d\n", server, proc);
 
265
 
 
266
    return 0;
 
267
}
 
268
 
 
269
/*\ client receives data from server
 
270
\*/
 
271
char *armci_ReadFromDirect (int proc, request_header_t *msginfo, int len)
 
272
{
 
273
 
 
274
    int server = armci_clus_id(proc);
 
275
    MPI_Status status;
 
276
 
 
277
    armci_mpi2_debug(armci_me, "armci_ReadFromDirect: proc=%d, server=%d, "
 
278
                     "msginfo=%p, bytes=%d (op=%d)\n", proc, server, msginfo,
 
279
                     len, msginfo->operation);
 
280
    
 
281
    if( !(server >= 0 && server < armci_nserver) )
 
282
       armci_die("armci_ReadFromDirect: Invalid server.", 0);
 
283
    
 
284
    MPI_Check(
 
285
       MPI_Recv(msginfo + 1, len, MPI_BYTE, server, ARMCI_MPI_SPAWN_TAG,
 
286
                MPI_COMM_CLIENT2SERVER, &status)
 
287
       );
 
288
 
 
289
    
 
290
    armci_mpi2_debug(armci_me, "recv msg from server(%d), fwd by client %d\n",
 
291
                     server, proc);
 
292
 
 
293
#if MPI_SPAWN_DEBUG
 
294
    {
 
295
       int count;
 
296
       MPI_Get_count(&status, MPI_BYTE, &count);
 
297
       if (count != len) 
 
298
       {
 
299
          armci_mpi2_debug(armci_me, "armci_ReadFromDirect: got %d bytes, "
 
300
                           "expected %d bytes\n", count, len);
 
301
          armci_die("armci_ReadFromDirect: MPI_Recv failed.", count);
 
302
       }
 
303
    }
 
304
#endif
 
305
    
 
306
 return (char *) (msginfo+1);
 
307
}
 
308
 
 
309
/*\ client receives strided data from server
 
310
\*/
 
311
void armci_ReadStridedFromDirect(int proc, request_header_t* msginfo,
 
312
                                 void *ptr, int strides, int stride_arr[],
 
313
                                 int count[])
 
314
{
 
315
 
 
316
    int server=armci_clus_id(proc);
 
317
    
 
318
    armci_mpi2_debug(armci_me, "armci_ReadStridedFromDirect: proc=%d "
 
319
                     "stride_levels=%d, server=%d bytes=%d (op=%d)\n",
 
320
                     proc, strides, server, msginfo->datalen,
 
321
                     msginfo->operation);
 
322
 
 
323
    
 
324
    if( !(server >= 0 && server < armci_nserver) )
 
325
       armci_die("armci_ReadStridedFromDirect: Invalid server.", 0);
 
326
 
 
327
#ifdef MPI_USER_DEF_DATATYPE
 
328
    if(strides > 0) 
 
329
    {
 
330
       armci_mpi_strided2(RECV, ptr, strides, stride_arr, count, server,
 
331
                          MPI_COMM_CLIENT2SERVER);
 
332
    }
 
333
    else
 
334
#endif
 
335
    {
 
336
       armci_mpi_strided(RECV, ptr, strides, stride_arr, count, server,
 
337
                         MPI_COMM_CLIENT2SERVER);
 
338
    }
 
339
}
 
340
 
 
341
 
 
342
 
 
343
/**
 
344
 * Platform specific server code ENDs here. (END)
 
345
 **************************************************************************/
 
346
 
 
347
static void armci_gather_hostnames(char **hostname_arr) 
 
348
{
 
349
    int i, j, k, namelen, is_master;
 
350
    char hostname[MPI_MAX_PROCESSOR_NAME], *hostnames=NULL;
 
351
    int *master_arr=NULL;
 
352
    
 
353
    master_arr = (int*)  malloc(armci_nproc * sizeof(int));
 
354
    hostnames  = (char*) malloc(armci_nproc * MPI_MAX_PROCESSOR_NAME *
 
355
                                   sizeof(char));
 
356
    
 
357
    if(hostnames==NULL || master_arr==NULL) 
 
358
    {
 
359
       armci_die("armci_gather_hostnames: malloc failed.", 0);
 
360
    }
 
361
    
 
362
    
 
363
    MPI_Get_processor_name(hostname, &namelen);
 
364
    MPI_Check(
 
365
       MPI_Allgather(hostname,  MPI_MAX_PROCESSOR_NAME, MPI_CHAR,
 
366
                     hostnames, MPI_MAX_PROCESSOR_NAME, MPI_CHAR,
 
367
                     ARMCI_COMM_WORLD)
 
368
       );
 
369
 
 
370
    if(armci_me == armci_master) 
 
371
    {
 
372
       is_master = 1;
 
373
    }
 
374
    else 
 
375
    {
 
376
       is_master = 0;
 
377
    }
 
378
 
 
379
    MPI_Check(MPI_Allgather(&is_master, 1, MPI_INT, master_arr, 1, MPI_INT,
 
380
                            ARMCI_COMM_WORLD));
 
381
 
 
382
    {
 
383
       /* get only the hostname of armci master processes */
 
384
       for(i=0,j=0,k=0; i<armci_nproc; i++) 
 
385
       {
 
386
          if(master_arr[i] == 1) 
 
387
          {
 
388
             if(j>=armci_nserver)
 
389
                armci_die("armci_gather_hostnames: Invalid masters.",0);
 
390
             strncpy(hostname_arr[j++], &hostnames[k], MPI_MAX_PROCESSOR_NAME);
 
391
          }
 
392
          k += MPI_MAX_PROCESSOR_NAME;
 
393
       }
 
394
    }
 
395
    
 
396
    free(hostnames);
 
397
    free(master_arr);
 
398
}
 
399
 
 
400
 
 
401
void select_server_program(char *server_program,
 
402
                           int num_procs)
 
403
{
 
404
 
 
405
    strcpy(server_program, (*_armci_argv)[0]);
 
406
 
 
407
    return;
 
408
}
 
409
 
 
410
 
 
411
static void armci_mpi2_spawn() 
 
412
{
 
413
 
 
414
    int i;
 
415
    char server_program[100];
 
416
    char **command_arr=NULL, **hostname_arr=NULL, **nid_arr=NULL;
 
417
    int *size_arr=NULL;
 
418
    MPI_Info *info_arr;
 
419
    
 
420
    /* we need to start 1 data server process on each node. So a total of
 
421
       "armci_nclus" data servers */
 
422
    armci_nserver = armci_nclus;
 
423
    select_server_program(server_program, armci_nserver);
 
424
    
 
425
    armci_mpi2_debug(0, "armci_mpi2_init(): Spawning %d data server processes "
 
426
                     "running %s\n", armci_nserver, server_program);
 
427
 
 
428
    /* allocate necessary data structures */
 
429
    {
 
430
       command_arr  = (char**)    malloc(armci_nserver * sizeof(char*));
 
431
       size_arr     = (int*)      malloc(armci_nserver * sizeof(int));
 
432
       info_arr     = (MPI_Info*) malloc(armci_nserver * sizeof(MPI_Info));
 
433
       hostname_arr = (char**)    malloc(armci_nserver * sizeof(char*));
 
434
#ifdef SPAWN_CRAY_XT
 
435
       nid_arr      = (char**)    malloc(armci_nserver * sizeof(char*));;
 
436
#endif
 
437
       for(i=0; i<armci_nserver; i++) 
 
438
       {
 
439
          hostname_arr[i] = (char*)malloc(MPI_MAX_PROCESSOR_NAME*sizeof(char));
 
440
       }
 
441
 
 
442
       if(command_arr==NULL || size_arr==NULL || info_arr==NULL ||
 
443
          hostname_arr==NULL) 
 
444
       {
 
445
          armci_die("armci_mpi2_spawn: malloc failed.", 0);
 
446
       }
 
447
    }
 
448
    
 
449
    /**
 
450
     * 1. root process collects hostnames (i.e. machine names) of where to
 
451
     * spawn dataservers. ARMCI masters of respective node will return their
 
452
     * hostnames. 
 
453
     */
 
454
    armci_gather_hostnames(hostname_arr);
 
455
    
 
456
       
 
457
    /** 2. initialize MPI_Comm_spawn_multiple() arguments */
 
458
    {   
 
459
       for(i=0; i<armci_nserver; i++)
 
460
       {
 
461
          command_arr[i] = (*_armci_argv)[0];  /*CHECK: path needs fix */
 
462
          size_arr[i]    = 1;                /* 1 data server in each node */
 
463
          MPI_Info_create(&info_arr[i]);
 
464
#ifdef SPAWN_CRAY_XT
 
465
          asprintf(&nid_arr[i], "%d", atoi((hostname_arr[i] + 3)));
 
466
          MPI_Info_set(info_arr[i], "host", nid_arr[i]); /*portability? */
 
467
#else
 
468
          MPI_Info_set(info_arr[i], "host", hostname_arr[i]); /*portability? */
 
469
#endif
 
470
       }
 
471
    }
 
472
 
 
473
    
 
474
    /**
 
475
     * 3. MPI_Comm_spawn_multiple(): This is a collective call.
 
476
     * Intercommunicator "ds_intercomm" contains only new dataserver processes.
 
477
     */
 
478
    MPI_Check(
 
479
       MPI_Comm_spawn_multiple(armci_nserver, command_arr, MPI_ARGVS_NULL,
 
480
                               size_arr, info_arr, ARMCI_ROOT, ARMCI_COMM_WORLD,
 
481
                               &MPI_COMM_CLIENT2SERVER, MPI_ERRCODES_IGNORE)
 
482
       );
 
483
 
 
484
 
 
485
    {  
 
486
       for(i=0; i<armci_nserver; i++)  free(hostname_arr[i]);
 
487
       
 
488
       free(command_arr);
 
489
       free(size_arr);
 
490
       free(info_arr);
 
491
       free(hostname_arr);
 
492
#ifdef SPAWN_CRAY_XT
 
493
       free(nid_arr);
 
494
#endif
 
495
    }
 
496
}
 
497
       
 
498
/**
 
499
 * Create server processes. This is called in armci_start_server.
 
500
 * Must be called after armci_init_clusinfo().
 
501
 */
 
502
void armci_create_server_MPIprocess ()
 
503
{
 
504
    int rank, size, flag, i;
 
505
 
 
506
    MPI_Initialized(&flag);
 
507
    if (flag == 0)
 
508
       armci_die("ARMCI error: MPI_Init must be called before PARMCI_Init()",0);
 
509
    
 
510
    MPI_Comm_rank(ARMCI_COMM_WORLD, &rank);
 
511
    MPI_Comm_size(ARMCI_COMM_WORLD, &size);
 
512
 
 
513
    /* spawn one data server process (i.e. additional MPI proc) on each node */
 
514
    armci_mpi2_spawn();
 
515
    
 
516
    /**
 
517
     * Armci masters send the following info to their corresponding server as
 
518
     * the server was not part of the initialization step in PARMCI_Init()
 
519
     *    1. cluster info ( i.e. armci_init_clusinfo() )
 
520
     *    2. lock info    ( i.e.armci_allocate_locks() )
 
521
     */
 
522
    
 
523
    if(armci_me == armci_master) {
 
524
       int msg[3];
 
525
       long shm_info[3], shmoffset;
 
526
       int shmid;
 
527
       size_t shmsize;
 
528
       
 
529
       /**
 
530
        * 1. Cluster info
 
531
        */
 
532
       msg[0] = ARMCI_MPI_SPAWN_INIT_TAG + armci_clus_me; /* for validation */
 
533
       msg[1] = armci_me;
 
534
       msg[2] = armci_clus_info[armci_clus_me].nslave;
 
535
       MPI_Send(msg, 3, MPI_INT, armci_clus_me, ARMCI_MPI_SPAWN_INIT_TAG,
 
536
                MPI_COMM_CLIENT2SERVER);
 
537
 
 
538
       /* send the entire clus info to its data server */
 
539
       MPI_Send(armci_clus_info, armci_nclus*sizeof(armci_clus_t), MPI_BYTE,
 
540
                armci_clus_me, ARMCI_MPI_SPAWN_INIT_TAG,
 
541
                MPI_COMM_CLIENT2SERVER);
 
542
       
 
543
       /**
 
544
        * 2. lock info
 
545
        */
 
546
       armci_get_shmem_info((char*)_armci_int_mutexes, &shmid, &shmoffset,
 
547
                            &shmsize);
 
548
       shm_info[0] = (long) shmid;
 
549
       shm_info[1] = (long) shmoffset;
 
550
       shm_info[2] = (long) shmsize;
 
551
       
 
552
       MPI_Send(shm_info, 3, MPI_LONG, armci_clus_me, ARMCI_MPI_SPAWN_INIT_TAG,
 
553
                MPI_COMM_CLIENT2SERVER);       
 
554
    }
 
555
     
 
556
 
 
557
    /* initialize tags for flow control */
 
558
    _armci_mpi_tag = (int*) malloc(armci_nserver*sizeof(int));
 
559
    for(i=0; i<armci_nserver; i++)
 
560
       _armci_mpi_tag[i]=ARMCI_MPI_SPAWN_TAG_BEGIN;
 
561
    
 
562
    /* makesure all processes sync here. CHECK: does it ensure global sync ? */
 
563
    MPI_Barrier(ARMCI_COMM_WORLD);
 
564
    
 
565
    armci_mpi2_debug(0, "armci_create_server_MPIprocess: Servers spawned!\n");
 
566
}
 
567
 
 
568
/*
 
569
  CHECK:
 
570
  =====
 
571
  1. MPI_Info portability issue. e.g. MPI_Info_set
 
572
 
 
573
  2. For sockets with server process option (i.e. not thread, but an actual
 
574
  process as data server), all clients call armci_init_connections() in
 
575
  armci_start_server(), which ic called by PARMCI_Init(). Should this init
 
576
  connections be done for MPI_SPAWN as well
 
577
  NOTE: armci_init_connections call _armci_buf_init(). In our MPI_SPAWN case we
 
578
  never call _armci_buf_init() either in clients or in (spawned) dataservers.
 
579
 
 
580
  3. Implement non-blocking in future for sure. For example:
 
581
  armci_save_strided_dscr() is disabled in armci_rem_strided (request.c) and
 
582
  armci_complete_vector_get is enabled in armci_rev_vector (request.c)
 
583
 
 
584
*/
 
585