~ubuntu-branches/ubuntu/trusty/nwchem/trusty-proposed

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src-gemini/portals_cp.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
   portals_cp.c  -- compute process portals calls
 
7
   author: ryan olson
 
8
   email:  ryan@cray.com
 
9
\* ---------------------------------------------------------------------------------------------- */
 
10
 # include "armcip.h"
 
11
 # include <assert.h>
 
12
 # include <stdio.h>
 
13
 # include <sched.h>
 
14
 # include <unistd.h>
 
15
 
 
16
/* ---------------------------------------------------------------------------------------------- *\
 
17
\* ---------------------------------------------------------------------------------------------- */
 
18
   static ptl_handle_ni_t cp_nih;
 
19
   static ptl_handle_eq_t cp_eqh;
 
20
   static ptl_handle_eq_t cp_tx_eqh;
 
21
 
 
22
   static void  *portals_eager_send_buffer  = NULL;
 
23
   static size_t portals_unique_msg_counter = 373;
 
24
 
 
25
   static int portals_smp_sem = -1;
 
26
   static int *active_requests_by_node = NULL;
 
27
 
 
28
/* ---------------------------------------------------------------------------------------------- *\
 
29
\* ---------------------------------------------------------------------------------------------- */
 
30
   int portals_cp_finished = 0;
 
31
 
 
32
 
 
33
/* ---------------------------------------------------------------------------------------------- *\
 
34
   Implementation
 
35
\* ---------------------------------------------------------------------------------------------- */
 
36
 
 
37
int 
 
38
portals_cp_init(void) 
 
39
{
 
40
        int rc;
 
41
        int me;
 
42
        ptl_process_id_t id;
 
43
 
 
44
        rc = portals_init(&cp_nih);
 
45
        if(rc != PTL_OK) {
 
46
           printf("error in portals_init: err %d\n",rc);
 
47
           Fatal_error(rc);
 
48
        }
 
49
 
 
50
        rc = portals_create_eq(cp_nih,10*PORTALS_MAX_DESCRIPTORS,&cp_eqh);
 
51
        if(rc != PTL_OK) {
 
52
           printf("failed to create cp event queue; err %d\n",rc);
 
53
           Fatal_error(911);
 
54
        }
 
55
 
 
56
        rc = portals_create_eq(cp_nih,30,&cp_tx_eqh);
 
57
        if(rc != PTL_OK) {
 
58
           printf("failed to create cp_tx event queue; err %d\n",rc);
 
59
           Fatal_error(911);
 
60
        }
 
61
 
 
62
        rc = portals_cp_getid(&id);
 
63
        if(rc != PTL_OK) {
 
64
           printf("failed to get the portals id; err %d\n",rc);
 
65
           Fatal_error(rc);
 
66
        }
 
67
 
 
68
     /* creating an smp/intra-node communicator */
 
69
        MPI_Comm_rank(ARMCI_COMM_WORLD,&me);
 
70
        MPI_Comm_split(ARMCI_COMM_WORLD,id.nid,me,&portals_smp_comm);
 
71
 
 
72
     /* set affinity */
 
73
      # ifdef PORTALS_AFFINITY
 
74
        int smp_np, smp_me;
 
75
        unsigned long mask;
 
76
        unsigned int len = sizeof(mask);
 
77
        unsigned long ncpus;
 
78
        unsigned int nsockets, siblings;
 
79
        int cores_per_socket, cps_per_socket;
 
80
        int verbose = 0;
 
81
 
 
82
        MPI_Comm_size(portals_smp_comm,&smp_np);
 
83
        MPI_Comm_rank(portals_smp_comm,&smp_me);
 
84
 
 
85
 
 
86
        if((ncpus = sysconf(_SC_NPROCESSORS_ONLN)) < 0) {
 
87
           printf("%d [cp] sysconf(_SC_NPROCESSORS_ONLN) failed; err=%d\n", ncpus);
 
88
           armci_die("sysconf in init_throttle",911);
 
89
        }
 
90
 
 
91
           
 
92
        if(sched_getaffinity(0, len, &mask) < 0) {
 
93
           perror("sched_getaffinity");
 
94
           armci_die("getaffinity error in ds_init",911);
 
95
        }
 
96
 
 
97
        if(armci_clus_me == 0 && /* verbose */ 0 ) {
 
98
           printf("%d [cp]: old affinity = 0x%x, ncpus = %d\n", armci_me, mask, ncpus);
 
99
        }
 
100
 
 
101
        if(smp_me == 0) {
 
102
           mask = 1 << (ncpus-1);
 
103
           if(sched_setaffinity(0, len, (cpu_set_t *) &mask) < 0) {
 
104
              perror("sched_setaffinity to probe the socket count");
 
105
              armci_die("setaffinity error in ds_init",911);
 
106
           }
 
107
           siblings = cpuid_ebx(1) >>16 & 0xff;
 
108
           nsockets = ncpus / siblings;
 
109
        } 
 
110
        MPI_Bcast(&nsockets,1,MPI_INT,0,portals_smp_comm);
 
111
           
 
112
        cores_per_socket = ncpus/nsockets;
 
113
        cps_per_socket  = (smp_np / nsockets);
 
114
        cps_per_socket += (smp_np % nsockets);
 
115
        if(nsockets > 2) {
 
116
           armci_die("nsockets > 2 not supported",911);
 
117
        }
 
118
        if(smp_me < cps_per_socket) {
 
119
           mask = 1 << smp_me;
 
120
        } else {
 
121
           mask = 1 << (smp_me + (cores_per_socket - cps_per_socket));
 
122
        }
 
123
 
 
124
        if(sched_setaffinity(0, len, (cpu_set_t *) &mask) < 0) {
 
125
           perror("sched_setaffinity");
 
126
           armci_die("setaffinity error in ds_init",911);
 
127
        }
 
128
 
 
129
        if(sched_getaffinity(0, len, &mask) < 0) {
 
130
           perror("sched_getaffinity");
 
131
           armci_die("getaffinity error (#2) in ds_init",911);
 
132
        }
 
133
 
 
134
        if(armci_clus_me == 0 && verbose) {
 
135
           printf("%d [cp]: new affinity = 0x%x, ncpus = %d\n", armci_me, mask, ncpus);
 
136
        }
 
137
      # endif
 
138
 
 
139
        return PTL_OK;
 
140
}
 
141
   
 
142
 
 
143
int
 
144
portals_cp_finalize()
 
145
{
 
146
        int rc;
 
147
 
 
148
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
 
149
        armci_semrm(portals_smp_sem);
 
150
      # endif
 
151
 
 
152
        rc = portals_free_eq(cp_eqh);
 
153
        if (rc != PTL_OK) {
 
154
           printf("error freeing cp_eqh; err %d\n",rc);
 
155
        }
 
156
 
 
157
        MPI_Barrier(ARMCI_COMM_WORLD);
 
158
        MPI_Finalize();
 
159
 
 
160
        portals_cp_finished = 1;
 
161
        exit(0);
 
162
 
 
163
        return PTL_OK;
 
164
//      return portals_finalize(cp_nih);
 
165
}
 
166
 
 
167
 
 
168
int
 
169
portals_cp_getid(ptl_process_id_t *id)
 
170
{
 
171
        return portals_getid(cp_nih, id);
 
172
}
 
173
 
 
174
 
 
175
static size_t
 
176
portals_get_unique_msg_id(void) {
 
177
   size_t val = armci_me*1000;
 
178
   portals_unique_msg_counter++;
 
179
   if(portals_unique_msg_counter == 1000) portals_unique_msg_counter=1;
 
180
   val += portals_unique_msg_counter;
 
181
   return val;
 
182
}
 
183
 
 
184
 
 
185
static void
 
186
portals_req_clear(portals_ds_req_t *req)
 
187
{
 
188
        req->active         = 0;
 
189
        req->unique_msg_id  = 0;
 
190
 
 
191
        req->req_desc.done  = 1;
 
192
        req->req_desc.state = 0;
 
193
        req->req_desc.eqh   = cp_tx_eqh;
 
194
 
 
195
        req->ack_desc.done  = 1;
 
196
        req->ack_desc.state = 0;
 
197
        req->ack_desc.eqh   = cp_eqh;
 
198
 
 
199
        req->data_desc.done  = 1;
 
200
        req->data_desc.state = 0;
 
201
        req->data_desc.eqh   = cp_eqh;
 
202
 
 
203
        req->remote_node     = -1;
 
204
}
 
205
 
 
206
 
 
207
static ptl_process_id_t
 
208
portals_get_dsid_from_node(int remote_node)
 
209
{
 
210
        int rank = armci_clus_info[remote_node].master;
 
211
        if(portals_cloned_id_map) return portals_cloned_id_map[rank];
 
212
        else                      return portals_id_map[rank];
 
213
}
 
214
 
 
215
 
 
216
static ptl_process_id_t
 
217
portals_get_dsid_from_rank(int remote_id)
 
218
{
 
219
        if(portals_cloned_id_map) return portals_cloned_id_map[remote_id];
 
220
        else                      return portals_id_map[remote_id];
 
221
}
 
222
 
 
223
void
 
224
portals_req_nbsend(void *buffer, size_t size, portals_ds_req_t *req)
 
225
{
 
226
        int rc;
 
227
        portals_desc_t *desc = &req->req_desc;
 
228
 
 
229
        assert(req->unique_msg_id);
 
230
        assert(size < portalsMaxEagerMessageSize);
 
231
        assert(req->remote_node >= 0);
 
232
 
 
233
     /* ---------------------------------------------------------------------------- *\
 
234
        if we get here, we can guarantee that where are no outstanding requests from
 
235
        this PE to the remote node; however, we can not guarantee that other PEs on
 
236
        this node aren't talking to the intended data server ... so now we wait on
 
237
        value in the "shared" array.
 
238
     \* ---------------------------------------------------------------------------- */
 
239
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
 
240
        int got_lock = 0;
 
241
        while(!got_lock) {
 
242
           portalsSpinLockOnInt(&active_requests_by_node[req->remote_node],0,1000);
 
243
           semaphoreAcquire(portals_smp_sem,1,PORTALS_WRITE_ACCESS);
 
244
           if(active_requests_by_node[req->remote_node] == 0) {
 
245
             active_requests_by_node[req->remote_node] = 1;
 
246
             got_lock = 1;
 
247
           }
 
248
           semaphoreRelease(portals_smp_sem,1,PORTALS_WRITE_ACCESS);
 
249
        }
 
250
      # endif
 
251
 
 
252
        desc->buffer = buffer;
 
253
        desc->length = size;
 
254
        desc->id     = req->dsid;
 
255
        desc->mbits  = MATCH_ALL_MBITS;
 
256
        desc->hdr    = req->unique_msg_id;
 
257
        desc->state  = 0;
 
258
        desc->eqh    = cp_tx_eqh;
 
259
        desc->nih    = cp_nih;
 
260
 
 
261
        rc = portals_put(desc);
 
262
        if(rc != PTL_OK) {
 
263
                printf("portals_put err %d\n",rc);
 
264
                Fatal_error(rc);
 
265
        }
 
266
}
 
267
 
 
268
void
 
269
portals_req_send(void *buffer, size_t size, portals_ds_req_t *req)
 
270
{
 
271
        int rc;
 
272
        portals_desc_t *desc = &req->req_desc;
 
273
 
 
274
        portals_req_nbsend(buffer,size,req);
 
275
 
 
276
        rc = portals_wait(desc);
 
277
        if(rc != PTL_OK) {
 
278
                printf("portals_wait err %d\n",rc);
 
279
                Fatal_error(rc);
 
280
        }
 
281
}
 
282
 
 
283
 
 
284
static inline void
 
285
portals_req_wait(portals_ds_req_t *req) 
 
286
{
 
287
        int rc;
 
288
 
 
289
        if(req->req_desc.state) {
 
290
           rc = portals_wait( &(req->req_desc) );
 
291
           if(rc != PTL_OK) {
 
292
              printf("portals wait error on req_desc in req_wait; err=%d\n",rc);
 
293
              Fatal_error(rc);
 
294
           }
 
295
        }
 
296
 
 
297
        if(req->ack_desc.state) {
 
298
           rc = portals_wait( &(req->ack_desc) );
 
299
           if(rc != PTL_OK) {
 
300
              printf("portals wait error on ack_desc in req_wait; err=%d\n",rc);
 
301
              Fatal_error(rc);
 
302
           }
 
303
        }
 
304
        if(req->data_desc.state) {
 
305
           rc = portals_wait( &(req->data_desc) );
 
306
           if(rc != PTL_OK) {
 
307
              printf("portals wait error on data_desc in req_wait; err=%d\n",rc);
 
308
              Fatal_error(rc);
 
309
           }
 
310
        }
 
311
 
 
312
        req->active = 0;
 
313
        return;
 
314
}
 
315
 
 
316
 
 
317
void
 
318
portalsWaitOnRequest(portals_ds_req_t *req) {
 
319
        portals_req_wait(req);
 
320
}
 
321
 
 
322
 
 
323
static int
 
324
portals_prepost_ack_from_ds(portals_ds_req_t *req)
 
325
 
326
        int rc;
 
327
        ptl_md_t md;
 
328
        portals_desc_t *desc = &req->ack_desc;
 
329
        unsigned long mbits = req->unique_msg_id;
 
330
 
 
331
        assert(req->unique_msg_id);
 
332
        assert(req->remote_node >= 0);
 
333
 
 
334
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
 
335
        desc->buffer = &active_requests_by_node[req->remote_node];
 
336
        desc->length = sizeof(int);
 
337
      # else
 
338
        desc->buffer = NULL;
 
339
        desc->length = 0;
 
340
      # endif
 
341
        desc->id     = req->dsid;
 
342
        desc->mbits  = mbits | DS_RESPONSE_ACK;
 
343
        desc->hdr    = mbits;
 
344
        desc->eqh    = cp_eqh;
 
345
 
 
346
        rc = portals_me_attach(cp_nih,desc->id,desc->mbits,0,&desc->meh);
 
347
        if(rc != PTL_OK) {
 
348
                printf("me failed in prepost ack\n");
 
349
                Fatal_error(rc);
 
350
        }
 
351
 
 
352
        md.start     = desc->buffer;
 
353
        md.length    = desc->length;
 
354
        md.threshold = 1;
 
355
        md.options   = PTL_MD_OP_PUT | PTL_MD_EVENT_START_DISABLE;
 
356
        md.user_ptr  = desc;
 
357
        md.eq_handle = cp_eqh;
 
358
 
 
359
        rc = portals_md_attach(desc->meh,md,PTL_UNLINK,&desc->mdh);
 
360
        if(rc != PTL_OK) {      
 
361
                printf("md failed in prepost ack\n");
 
362
                Fatal_error(rc);
 
363
        } 
 
364
 
 
365
        // desc->state = STATE_PUT_END;
 
366
        // |= needed for rendez-vous gets; put and get using the same descriptor
 
367
        desc->state |= STATE_PUT_END;
 
368
        desc->done  = 0;
 
369
}
 
370
 
 
371
 
 
372
static int
 
373
portals_prepost_put_from_ds(void *buffer, size_t size, portals_ds_req_t *req) 
 
374
{
 
375
        int rc;
 
376
        int nputs;
 
377
        ptl_md_t md;
 
378
        portals_desc_t *desc = &req->data_desc;
 
379
        unsigned long mbits = req->unique_msg_id;
 
380
 
 
381
        assert(req->unique_msg_id);
 
382
 
 
383
        desc->buffer = buffer;
 
384
        desc->length = size;
 
385
        desc->id     = req->dsid;
 
386
        desc->mbits  = mbits | DS_RESPONSE_PUT;
 
387
        desc->hdr    = mbits;
 
388
        desc->eqh    = cp_eqh;
 
389
 
 
390
        rc = portals_me_attach(cp_nih,desc->id,desc->mbits,0,&desc->meh);
 
391
        if(rc != PTL_OK) {
 
392
                printf("me failed in prepost put\n");
 
393
                Fatal_error(rc);
 
394
        }
 
395
 
 
396
        md.start     = buffer;
 
397
        md.length    = size;
 
398
        md.threshold = desc->noperations;
 
399
        md.options   = PTL_MD_OP_PUT
 
400
                     | PTL_MD_EVENT_AUTO_UNLINK_ENABLE
 
401
                     | PTL_MD_EVENT_START_DISABLE 
 
402
                     | PTL_MD_EVENT_END_DISABLE;
 
403
        md.user_ptr  = (void *) desc;
 
404
        md.eq_handle = cp_eqh;
 
405
 
 
406
        rc = portals_md_attach(desc->meh,md,PTL_UNLINK,&desc->mdh);
 
407
        if(rc != PTL_OK) {      
 
408
                printf("md failed in prepost put\n");
 
409
                Fatal_error(rc);
 
410
        } 
 
411
 
 
412
        // desc->state = STATE_UNLINK;
 
413
        // |= needed for rendez-vous gets; put and get using the same descriptor
 
414
        desc->state |= STATE_UNLINK;
 
415
        desc->done  = 0;
 
416
}
 
417
 
 
418
 
 
419
static int
 
420
portals_prepost_get_from_ds(void *buffer, size_t size, portals_ds_req_t *req) {
 
421
        
 
422
        int rc;
 
423
        ptl_md_t md;
 
424
        portals_desc_t *desc = &req->data_desc;
 
425
        unsigned long mbits = req->unique_msg_id;
 
426
 
 
427
        assert(req->unique_msg_id);
 
428
 
 
429
        desc->buffer = buffer;
 
430
        desc->length = size;
 
431
        desc->id     = req->dsid;
 
432
        desc->mbits  = mbits | DS_RESPONSE_GET;
 
433
        desc->hdr    = mbits;
 
434
        desc->eqh    = cp_eqh;
 
435
 
 
436
        rc = portals_me_attach(cp_nih,desc->id,desc->mbits,0,&desc->meh);
 
437
        if(rc != PTL_OK) {
 
438
                printf("me failed in prepost get\n");
 
439
                Fatal_error(rc);
 
440
        }
 
441
 
 
442
        md.start     = buffer;
 
443
        md.length    = size;
 
444
        md.threshold = desc->noperations;
 
445
        md.options   = PTL_MD_OP_GET
 
446
                     | PTL_MD_EVENT_START_DISABLE;
 
447
                  // | PTL_MD_EVENT_AUTO_UNLINK_ENABLE
 
448
                  // | PTL_MD_EVENT_START_DISABLE 
 
449
                  // | PTL_MD_EVENT_END_DISABLE;
 
450
        md.user_ptr  = (void *) desc;
 
451
        md.eq_handle = cp_eqh;
 
452
 
 
453
        rc = portals_md_attach(desc->meh,md,PTL_UNLINK,&desc->mdh);
 
454
        if(rc != PTL_OK) {      
 
455
                printf("md failed in prepost get\n");
 
456
                Fatal_error(rc);
 
457
        } 
 
458
 
 
459
     // printf("%d: preposted get of lenght=%ld\n",armci_me,size);
 
460
     // desc->state = STATE_UNLINK;
 
461
        // desc->state = STATE_GET_END;
 
462
        // |= needed for rendez-vous gets; put and get using the same descriptor
 
463
        desc->state |= STATE_GET_END;
 
464
        desc->done  = 0;
 
465
}
 
466
 
 
467
 
 
468
void portalsBlockingRemoteOperationToNode(void *buffer, size_t length, int remote_node) {
 
469
        portals_ds_req_t req;
 
470
        portals_req_clear(&req);        
 
471
        portalsRemoteOperationToNode(buffer,length,remote_node,&req);
 
472
        portalsWaitOnRequest(&req);
 
473
}
 
474
 
 
475
 
 
476
void portalsRemoteOperationToNode(void *buffer, size_t length, int remote_node, portals_ds_req_t *req)
 
477
{
 
478
        ptl_process_id_t id = portals_get_dsid_from_node(remote_node);
 
479
        req->remote_node = remote_node;
 
480
        portalsRemoteOperation(buffer,length,id,req);
 
481
}
 
482
 
 
483
 
 
484
/*
 
485
void portalsRemoteOperationToRank(void *buffer, size_t length, int remote_rank, portals_ds_req_t *req) {
 
486
        ptl_process_id_t id = portals_get_dsid_from_rank(remote_rank);
 
487
        portalsRemoteOperation(buffer,length,id,req);
 
488
}
 
489
*/
 
490
 
 
491
 
 
492
void
 
493
portalsRemoteOperation(void *buffer, size_t length, ptl_process_id_t dsid, portals_ds_req_t *req)
 
494
{
 
495
     /* --------------------------------------------------------------------- *\
 
496
        initialize the data server request
 
497
     \* --------------------------------------------------------------------- */
 
498
     // portals_req_clear(req);
 
499
        req->active = 1;
 
500
        req->unique_msg_id = portals_get_unique_msg_id();
 
501
        req->dsid = dsid;
 
502
 
 
503
     /* --------------------------------------------------------------------- *\
 
504
        the only response from the ds will be a 0-byte ack coming in as a put
 
505
     \* --------------------------------------------------------------------- */
 
506
        portals_prepost_ack_from_ds(req);
 
507
 
 
508
     /* --------------------------------------------------------------------- *\
 
509
        send data request; this is a completely blocking req
 
510
     \* --------------------------------------------------------------------- */
 
511
        portals_req_send(buffer,length,req);
 
512
}
 
513
 
 
514
 
 
515
void
 
516
portals_send_oper(int remote_node,int val, portals_ds_req_t *req)
 
517
{
 
518
        int rc;
 
519
        request_header_t msg;
 
520
 
 
521
     /* --------------------------------------------------------------------- *\
 
522
        initialize the data server request
 
523
     \* --------------------------------------------------------------------- */
 
524
        portals_req_clear(req);
 
525
        req->active = 1;
 
526
        req->unique_msg_id = portals_get_unique_msg_id();
 
527
        req->dsid = portals_get_dsid_from_node(remote_node);
 
528
        req->remote_node = remote_node;
 
529
 
 
530
     /* --------------------------------------------------------------------- *\
 
531
        the only response from the ds will be a 0-byte ack coming in as a put
 
532
     \* --------------------------------------------------------------------- */
 
533
        portals_prepost_ack_from_ds(req);
 
534
 
 
535
     /* --------------------------------------------------------------------- *\
 
536
        prepare data request and send it; this is a completely blocking req
 
537
     \* --------------------------------------------------------------------- */
 
538
        msg.operation = val;
 
539
        portals_req_send(&msg,sizeof(request_header_t),req);
 
540
        return; 
 
541
}
 
542
 
 
543
 
 
544
void
 
545
portals_send_QUIT(int remote_node)
 
546
{
 
547
        portals_ds_req_t req;
 
548
        portals_send_oper(remote_node,QUIT,&req);
 
549
        portals_req_wait(&req);
 
550
}
 
551
 
 
552
 
 
553
static int
 
554
portals_determine_remote_op_count(request_header_t *msg)
 
555
{
 
556
#ifdef DDI
 
557
        int nr,nc,np;
 
558
        int datatype_extent = sizeof(double);
 
559
 
 
560
     /* --------------------------------------------------------------------- *\
 
561
        previously we have worked with words, but to provide support for 
 
562
        other data types, we must work with bytes.  note to developers:
 
563
        datatype_extent = the size in bytes of the stored datatype
 
564
     \* --------------------------------------------------------------------- */
 
565
        if(msg->size*datatype_extent <= MAX_DS_MSG_SIZE) return 1;
 
566
 
 
567
     /* --------------------------------------------------------------------- *\
 
568
        the data must be moved in segments; determine patch dimensions
 
569
     \* --------------------------------------------------------------------- */
 
570
        nr = msg->ihi - msg->ilo + 1;
 
571
        nc = msg->jhi - msg->jlo + 1;
 
572
     
 
573
     /* --------------------------------------------------------------------- *\
 
574
        each column individually is too long to fit in the buffer
 
575
     \* --------------------------------------------------------------------- */
 
576
        if(nr*datatype_extent < MAX_DS_MSG_SIZE) {
 
577
 
 
578
        /* ------------------------------------------------------------------ *\
 
579
           np the number of "evenly" sized passed needed to send a column
 
580
        \* ------------------------------------------------------------------ */
 
581
           np = 2;
 
582
           while(((nr/np)+((nr%np)?1:0)*datatype_extent)>MAX_DS_MSG_SIZE) np++;
 
583
 
 
584
        /* ------------------------------------------------------------------ *\
 
585
           noperations is np times the number of columns to be sent
 
586
        \* ------------------------------------------------------------------ */
 
587
           return np*nc;
 
588
 
 
589
        }
 
590
 
 
591
     /* --------------------------------------------------------------------- *\
 
592
        determine the number of full columns that can be sent in one pass
 
593
        break down the subpatch on this metric
 
594
     \* --------------------------------------------------------------------- */
 
595
        else {
 
596
 
 
597
        /* ------------------------------------------------------------------ *\
 
598
           np is the number of passes needed to send the full patch which
 
599
           is broken down into "evenly" sized sets of columns that fit in 
 
600
           the allocated buffer region
 
601
        \* ------------------------------------------------------------------ */
 
602
           np = 2;
 
603
           while(nr*((nc/np)+((nc%np)?1:0))*datatype_extent>MAX_DS_MSG_SIZE) np++;
 
604
 
 
605
        /* ------------------------------------------------------------------ *\
 
606
           noperations is np 
 
607
        \* ------------------------------------------------------------------ */
 
608
           return np;
 
609
 
 
610
        }
 
611
 
 
612
        assert(0); // should not happen
 
613
        return -1;
 
614
#else
 
615
        return 1;
 
616
#endif
 
617
}
 
618
 
 
619
void 
 
620
portals_remote_rmw(void *buffer, request_header_t *msginfo, int remote_node, portals_ds_req_t *req)
 
621
{
 
622
        ptl_size_t length;
 
623
 
 
624
     /* --------------------------------------------------------------------- *\
 
625
        initialize the data server request
 
626
     \* --------------------------------------------------------------------- */
 
627
        portals_req_clear(req);
 
628
        req->active = 1;
 
629
        req->unique_msg_id = portals_get_unique_msg_id();
 
630
        req->dsid = portals_get_dsid_from_node(remote_node);
 
631
        req->remote_node = remote_node;
 
632
 
 
633
     /* --------------------------------------------------------------------- *\
 
634
        prepare the buffer into which the ds will put data
 
635
     \* --------------------------------------------------------------------- */
 
636
        req->data_desc.noperations=portals_determine_remote_op_count(msginfo);
 
637
        portals_prepost_put_from_ds(buffer,msginfo->datalen,req);
 
638
 
 
639
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
 
640
        portals_prepost_ack_from_ds(req);
 
641
      # endif
 
642
 
 
643
     /* --------------------------------------------------------------------- *\
 
644
        send data request
 
645
        note: from armci_send_req - if get, the value of bytes (local: length)
 
646
        is msginfo->dscrlen + (hdrlen=sizeof(request_header_t) ... this is
 
647
        the size of the "data server request message" to be sent
 
648
     \* --------------------------------------------------------------------- */
 
649
        length = sizeof(request_header_t) + msginfo->dscrlen + msginfo->datalen;
 
650
        portals_req_send(msginfo,length,req);
 
651
}
 
652
 
 
653
void 
 
654
portals_remote_get(void *buffer, request_header_t *msginfo, int remote_node)
 
655
{
 
656
        portals_ds_req_t req;
 
657
        portals_remote_nbget(buffer,msginfo,remote_node,&req);
 
658
        portals_req_wait(&req);
 
659
}
 
660
        
 
661
void 
 
662
portals_remote_nbget(void *buffer, request_header_t *msginfo, int remote_node, portals_ds_req_t *req)
 
663
{
 
664
        ptl_size_t length;
 
665
 
 
666
     /* --------------------------------------------------------------------- *\
 
667
        initialize the data server request
 
668
     \* --------------------------------------------------------------------- */
 
669
        portals_req_clear(req);
 
670
        req->active = 1;
 
671
        req->unique_msg_id = portals_get_unique_msg_id();
 
672
        req->dsid = portals_get_dsid_from_node(remote_node);
 
673
        req->remote_node = remote_node;
 
674
 
 
675
     /* --------------------------------------------------------------------- *\
 
676
        prepare the buffer into which the ds will put data
 
677
     \* --------------------------------------------------------------------- */
 
678
        req->data_desc.noperations=portals_determine_remote_op_count(msginfo);
 
679
        portals_prepost_put_from_ds(buffer,msginfo->datalen,req);
 
680
 
 
681
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
 
682
        portals_prepost_ack_from_ds(req);
 
683
      # endif
 
684
 
 
685
     /* --------------------------------------------------------------------- *\
 
686
        send data request
 
687
        note: from armci_send_req - if get, the value of bytes (local: length)
 
688
        is msginfo->dscrlen + (hdrlen=sizeof(request_header_t) ... this is
 
689
        the size of the "data server request message" to be sent
 
690
     \* --------------------------------------------------------------------- */
 
691
        length = sizeof(request_header_t) + msginfo->dscrlen;
 
692
 
 
693
      # if defined(PORTALS_USE_RENDEZ_VOUS)
 
694
        if(length < portalsMaxEagerMessageSize) portals_req_send(msginfo,length,req);
 
695
        else {
 
696
           req->data_desc.noperations = 1;
 
697
           portals_prepost_get_from_ds(msginfo,length,req);
 
698
        
 
699
        /* ------------------------------------------------------------------ *\
 
700
           send data request: branch here for eager vs. rendez-vous
 
701
        \* ------------------------------------------------------------------ */
 
702
           assert(length <= PORTALS_BUF_SIZE);
 
703
           portals_req_send(msginfo,sizeof(request_header_t),req);
 
704
        }
 
705
      # else   
 
706
        portals_req_send(msginfo,length,req);
 
707
      # endif
 
708
}
 
709
 
 
710
 
 
711
void 
 
712
portals_remote_put(void *buffer, request_header_t *msginfo, int remote_node)
 
713
{
 
714
        portals_ds_req_t req;
 
715
        portals_remote_nbput(buffer,msginfo,remote_node,&req);
 
716
        portals_req_wait(&req);
 
717
}
 
718
 
 
719
 
 
720
void 
 
721
portals_remote_nbput(void *buffer, request_header_t *msginfo, int remote_node, portals_ds_req_t *req)
 
722
{
 
723
        char *eagerBuffer = NULL;
 
724
        size_t eagerSendSize = 0;
 
725
 
 
726
     /* --------------------------------------------------------------------- *\
 
727
        initialize the data server request
 
728
     \* --------------------------------------------------------------------- */
 
729
        portals_req_clear(req);
 
730
        req->active = 1;
 
731
        req->unique_msg_id = portals_get_unique_msg_id();
 
732
        req->dsid = portals_get_dsid_from_node(remote_node);
 
733
        req->remote_node = remote_node;
 
734
 
 
735
     /* --------------------------------------------------------------------- *\
 
736
        prepost ack response from the data server
 
737
     \* --------------------------------------------------------------------- */
 
738
        portals_prepost_ack_from_ds(req);
 
739
 
 
740
     /* --------------------------------------------------------------------- *\
 
741
        eager vs. rendez-vous messaging
 
742
        eager: pack and send the message immediate (only for small messages)
 
743
        developers note: since portals_eager_send_buffer only exists once,
 
744
        this has to be a blocking send (ie the data is on the wire when
 
745
        req_send has finished and the buffer can be reused.  for greater
 
746
        overlap, create a set of eager send buffers ... however they have to
 
747
        be managed ... probably best to do it in a ring. 
 
748
 
 
749
        note: armci put/acc buffer is prepacked.
 
750
     \* --------------------------------------------------------------------- */
 
751
        eagerSendSize = sizeof(request_header_t) + msginfo->dscrlen + msginfo->datalen;
 
752
        if(eagerSendSize < portalsMaxEagerMessageSize) {
 
753
//         printf("sending eager message\n");
 
754
         # if 0 /* armci prepacked */
 
755
           eagerBuffer = (char *) portals_eager_send_buffer;
 
756
           memcpy(eagerBuffer,msginfo,sizeof(request_header_t));
 
757
           eagerBuffer += sizeof(request_header_t);
 
758
           memcpy(eagerBuffer,buffer,msginfo->bytes);
 
759
         # endif
 
760
           eagerBuffer = (char *) msginfo;  /* buffer == msginfo for armci */
 
761
           portals_req_send(eagerBuffer,eagerSendSize,req);
 
762
        }
 
763
 
 
764
     /* --------------------------------------------------------------------- *\
 
765
        rendez-vous: send the ds a request; ds will "get/pull" data 
 
766
     \* --------------------------------------------------------------------- */
 
767
        else {
 
768
         # ifdef PORTALS_USE_RENDEZ_VOUS
 
769
        /* ------------------------------------------------------------------ *\
 
770
           prepare the buffer into which the ds will put data
 
771
        \* ------------------------------------------------------------------ */
 
772
        // req->data_desc.noperations=portals_determine_remote_op_count(msginfo);
 
773
           req->data_desc.noperations = 1;
 
774
           portals_prepost_get_from_ds(msginfo,eagerSendSize,req);
 
775
 
 
776
        /* ------------------------------------------------------------------ *\
 
777
           send data request: branch here for eager vs. rendez-vous
 
778
        \* ------------------------------------------------------------------ */
 
779
           assert(eagerSendSize <= PORTALS_BUF_SIZE);
 
780
           portals_req_send(msginfo,sizeof(request_header_t),req);
 
781
 
 
782
         # else
 
783
           printf("%d [cp]: rendez-vous messaging not supported\n",armci_me);
 
784
           abort();
 
785
         # endif
 
786
        }
 
787
          
 
788
          
 
789
}
 
790
 
 
791
 
 
792
#if 0
 
793
void 
 
794
portals_remote_acc(void *buffer, request_header_t *msginfo, int remote_node)
 
795
{
 
796
        portals_ds_req_t req;
 
797
        portals_remote_nbacc(buffer,msginfo,remote_node,&req);
 
798
        portals_req_wait(&req);
 
799
}
 
800
 
 
801
 
 
802
void 
 
803
portals_remote_nbacc(void *buffer, request_header_t *msginfo, int remote_node, portals_ds_req_t *req)
 
804
{
 
805
        char *eagerBuffer = NULL;
 
806
        size_t eagerSendSize = 0;
 
807
 
 
808
        assert(msginfo->bytes);
 
809
 
 
810
     /* --------------------------------------------------------------------- *\
 
811
        initialize the data server request
 
812
     \* --------------------------------------------------------------------- */
 
813
        portals_req_clear(req);
 
814
        req->active = 1;
 
815
        req->unique_msg_id = portals_get_unique_msg_id();
 
816
        req->dsid = portals_get_dsid_from_node(remote_node);
 
817
 
 
818
     /* --------------------------------------------------------------------- *\
 
819
        eager vs. rendez-vous messaging
 
820
        eager: pack and send the message immediate (only for small messages)
 
821
     \* --------------------------------------------------------------------- */
 
822
        eagerSendSize = msginfo->bytes + sizeof(request_header_t);
 
823
        if(eagerSendSize < portalsMaxEagerMessageSize) {
 
824
 
 
825
        /* ------------------------------------------------------------------ *\
 
826
           prepost ack response from the data server
 
827
           developers note: if you globally fence an array with a collective
 
828
           operation prior to a section of code and defence it after, then you
 
829
           don't need to micro manage the fence on a per request basis in that
 
830
           section; this eliminates the need for a DS ack
 
831
        \* ------------------------------------------------------------------ */
 
832
           portals_prepost_ack_from_ds(req);
 
833
 
 
834
        /* ------------------------------------------------------------------ *\
 
835
           pack and send eager data request
 
836
           blocking for now, since portals_eager_send_buffer only exists once
 
837
           create multiple eager buffers for greater overlap
 
838
        \* ------------------------------------------------------------------ */
 
839
           eagerBuffer = (char *) portals_eager_send_buffer;
 
840
           memcpy(eagerBuffer,msginfo,sizeof(request_header_t));
 
841
           eagerBuffer += sizeof(request_header_t);
 
842
           memcpy(eagerBuffer,buffer,msginfo->bytes);
 
843
           eagerBuffer = (char *) portals_eager_send_buffer;
 
844
           portals_req_send(eagerBuffer,eagerSendSize,req);
 
845
        }
 
846
 
 
847
     /* --------------------------------------------------------------------- *\
 
848
        rendez-vous: send the ds a request; ds will "get/pull" data 
 
849
        developers note: a ds ack is not required for a rendez-vous pull,
 
850
        this is because the ds will not start the pull until a local fence
 
851
        has been raised (if needed - see note above)
 
852
     \* --------------------------------------------------------------------- */
 
853
        else {
 
854
        /* ------------------------------------------------------------------ *\
 
855
           prepare the buffer from which the ds will pull data
 
856
        \* ------------------------------------------------------------------ */
 
857
           req->data_desc.noperations=portals_determine_remote_op_count(msginfo);
 
858
           portals_prepost_get_from_ds(buffer,msginfo->bytes,req);
 
859
 
 
860
        /* ------------------------------------------------------------------ *\
 
861
           send data request
 
862
        \* ------------------------------------------------------------------ */
 
863
           portals_req_send(msginfo,sizeof(request_header_t),req);
 
864
           portalsWaitOnRequest(req);
 
865
        }
 
866
}
 
867
#endif
 
868
 
 
869
extern int armci_shmget(size_t,char*);
 
870
extern int armci_semget(int);
 
871
extern void *shmat(int,int,int);
 
872
 
 
873
void    
 
874
portals_cp_init_throttle(int nnodes) 
 
875
{         
 
876
        int i, shmid, smp_np, smp_me;
 
877
        size_t size = nnodes*sizeof(int);
 
878
        char *buf = NULL;
 
879
        
 
880
        MPI_Comm_size(portals_smp_comm,&smp_np);
 
881
        MPI_Comm_rank(portals_smp_comm,&smp_me);
 
882
 
 
883
 
 
884
      # ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE 
 
885
        if(armci_me == armci_master) {
 
886
           if(smp_me != 0) armci_die("smp_me and armci_master are different",911);
 
887
        }  
 
888
           
 
889
        if(smp_me == 0) {
 
890
           shmid = armci_shmget(size,"portals_cp_init_throttle");
 
891
           active_requests_by_node = (int *) shmat(shmid,0,0);
 
892
           if(active_requests_by_node == (void *) -1) {
 
893
              printf("%d [cp] shmat failed for shmid %d\n",armci_me,shmid);
 
894
              armci_die("badness",911);
 
895
           }
 
896
           armci_shmrm(shmid);
 
897
           for(i=0; i<nnodes; i++) active_requests_by_node[i] = 0;
 
898
           portals_smp_sem = armci_semget(2);
 
899
           semaphoreOperation(portals_smp_sem,1,PORTALS_WRITE_ACCESS);
 
900
        }
 
901
        
 
902
        MPI_Bcast(&shmid,1,MPI_INT,0,portals_smp_comm);
 
903
        MPI_Bcast(&portals_smp_sem,1,MPI_INT,0,portals_smp_comm);
 
904
        
 
905
        if(smp_me != 0) {
 
906
           active_requests_by_node = (int *) shmat(shmid,0,0);
 
907
        } else {
 
908
        }
 
909
 
 
910
        MPI_Barrier(portals_smp_comm);
 
911
      # endif
 
912
}
 
913