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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src-portals/memory.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
/* $Id: memory.c,v 1.56.2.3 2007-04-25 23:49:55 d3p687 Exp $ */
 
6
#ifndef NEW_MALLOC
 
7
#include <stdio.h>
 
8
#include <assert.h>
 
9
#include "armcip.h"
 
10
#include "message.h"
 
11
#include "kr_malloc.h"
 
12
 
 
13
#define DEBUG_ 0
 
14
#define USE_MALLOC
 
15
#define USE_SHMEM_
 
16
#define SHM_UNIT 1024
 
17
 
 
18
static context_t ctx_localmem;
 
19
/*
 
20
static context_t ctx_mlocalmem;
 
21
*/
 
22
#if defined(SYSV) || defined(WIN32) || defined(MMAP) || defined(HITACHI)
 
23
#include "shmem.h"
 
24
 
 
25
#if !defined(USE_SHMEM) && (defined(HITACHI) || defined(MULTI_CTX))
 
26
#    define USE_SHMEM
 
27
#endif
 
28
 
 
29
#if !(defined(LAPI)||defined(QUADRICS)||defined(SERVER_THREAD)) ||\
 
30
    defined(USE_SHMEM)
 
31
#define RMA_NEEDS_SHMEM
 
32
#endif
 
33
 
 
34
void kr_check_local()
 
35
{
 
36
#if 0
 
37
kr_malloc_print_stats(&ctx_localmem);
 
38
#endif
 
39
kr_malloc_verify(&ctx_localmem);
 
40
}
 
41
 
 
42
void  armci_print_ptr(void **ptr_arr, int bytes, int size, void* myptr, int off)
 
43
{
 
44
int i;
 
45
int nproc = armci_clus_info[armci_clus_me].nslave;
 
46
 
 
47
    ARMCI_PR_DBG("enter",0);
 
48
    for(i=0; i< armci_nproc; i++){
 
49
      int j;
 
50
      if(armci_me ==i){
 
51
        printf("%d master =%d nproc=%d off=%d\n",armci_me, 
 
52
               armci_master,nproc, off);
 
53
        printf("%d:bytes=%d mptr=%p s=%d ",armci_me, bytes, myptr,size);
 
54
        for(j = 0; j< armci_nproc; j++)printf(" %p",ptr_arr[j]);
 
55
        printf("\n"); fflush(stdout);
 
56
      }
 
57
      armci_msg_barrier();
 
58
    }
 
59
    ARMCI_PR_DBG("exit",0);
 
60
}
 
61
 
 
62
 
 
63
/*\ master exports its address of shmem region at the beggining of that region
 
64
\*/
 
65
static void armci_master_exp_attached_ptr(void* ptr)
 
66
{
 
67
    ARMCI_PR_DBG("enter",0);
 
68
    if(!ptr) armci_die("armci_master_exp_att_ptr: null ptr",0);
 
69
    *(volatile void**)ptr = ptr;
 
70
    ARMCI_PR_DBG("exit",0);
 
71
}
 
72
 
 
73
 
 
74
/*\ Collective Memory Allocation on shared memory systems
 
75
\*/
 
76
void armci_shmem_malloc(void *ptr_arr[], armci_size_t bytes)
 
77
{
 
78
    void *myptr=NULL, *ptr=NULL;
 
79
    long idlist[SHMIDLEN];
 
80
    long size=0, offset=0;
 
81
    long *size_arr;
 
82
    void **ptr_ref_arr;
 
83
    int  i,cn, len;
 
84
    int  nproc = armci_clus_info[armci_clus_me].nslave;
 
85
    ARMCI_PR_DBG("enter",0);
 
86
    bzero((char*)ptr_arr,armci_nproc*sizeof(void*));
 
87
 
 
88
    /* allocate work arrays */
 
89
    size_arr = (long*)calloc(armci_nproc,sizeof(long));
 
90
    if(!size_arr)armci_die("armci_malloc:calloc failed",armci_nproc);
 
91
    /* allocate arrays for cluster address translations */
 
92
 
 
93
    ptr_ref_arr = calloc(armci_nclus,sizeof(void*)); /* must be zero */
 
94
    if(!ptr_ref_arr)armci_die("armci_malloc:calloc 2 failed",armci_nclus);
 
95
 
 
96
    /* combine all memory requests into size_arr  */
 
97
    size_arr[armci_me] = bytes;
 
98
    armci_msg_lgop(size_arr, armci_nproc, "+");
 
99
 
 
100
    /* determine aggregate request size on the cluster node */
 
101
    for(i=0, size=0; i< nproc; i++) size += size_arr[i+armci_master];
 
102
 
 
103
    /* master process creates shmem region and then others attach to it */
 
104
    if(armci_me == armci_master ){
 
105
       /* can malloc if there is no data server process and has 1 process/node*/
 
106
#      ifndef RMA_NEEDS_SHMEM
 
107
             if(nproc == 1)
 
108
                myptr = kr_malloc(size, &ctx_localmem, 0, NULL, NULL);
 
109
             else
 
110
#      endif
 
111
                myptr = Create_Shared_Region(idlist+1,size,idlist);
 
112
       if(!myptr && size>0 )armci_die("armci_malloc: could not create", (int)(size>>10));
 
113
 
 
114
       /* place its address at begining of attached region for others to see */
 
115
       if(size)armci_master_exp_attached_ptr(myptr);
 
116
 
 
117
       if(DEBUG_){
 
118
         printf("%d:armci_malloc addr mptr=%p size=%ld\n",armci_me,myptr,size);
 
119
         fflush(stdout);
 
120
       }
 
121
    }
 
122
 
 
123
    /* broadcast shmem id to other processes on the same cluster node */
 
124
    armci_msg_clus_brdcst(idlist, SHMIDLEN*sizeof(long));
 
125
 
 
126
    if(armci_me != armci_master){
 
127
       myptr=(double*)Attach_Shared_Region(idlist+1,size,idlist[0]);
 
128
       if(!myptr)armci_die("armci_malloc: could not attach", (int)(size>>10));
 
129
 
 
130
       /* now every process in a SMP node needs to find out its offset
 
131
        * w.r.t. master - this offset is necessary to use memlock table
 
132
        */
 
133
       if(size) armci_set_mem_offset(myptr);
 
134
       if(DEBUG_){
 
135
          printf("%d:armci_malloc attached addr mptr=%p ref=%p size=%ld\n",
 
136
                 armci_me,myptr, *(void**)myptr,size); fflush(stdout);
 
137
       }
 
138
    }
 
139
#   if defined(DATA_SERVER)
 
140
       /* get server reference address for every cluster node to perform
 
141
        * remote address translation for global address space */
 
142
       if(armci_nclus>1){
 
143
          if(armci_me == armci_master){
 
144
#            ifdef SERVER_THREAD
 
145
               ptr_ref_arr[armci_clus_me]=myptr;
 
146
#            else
 
147
               {
 
148
                  extern int _armci_server_started;
 
149
                  if(_armci_server_started) {
 
150
                     armci_serv_attach_req(idlist, SHMIDLEN*sizeof(long), size,
 
151
                                           &ptr, sizeof(void*));
 
152
                     ptr_ref_arr[armci_clus_me]= myptr; /* from server*/
 
153
                  }
 
154
                  else /* server not yet started */
 
155
                     ptr_ref_arr[armci_clus_me]=myptr;
 
156
               }
 
157
 
 
158
               if(DEBUG_){
 
159
                 printf("%d:addresses server=%p myptr=%p\n",armci_me,ptr,myptr);
 
160
                 fflush(stdout);
 
161
               }
 
162
#            endif
 
163
          }
 
164
          /* exchange ref addr of shared memory region on every cluster node*/
 
165
          armci_exchange_address(ptr_ref_arr, armci_nclus);
 
166
        # ifdef ARMCI_REGISTER_SHMEM
 
167
          armci_register_shmem(myptr,size,idlist+1,idlist[0],ptr_ref_arr[armci_clus_me]);
 
168
        # endif
 
169
       }else {
 
170
          ptr_ref_arr[armci_master] = myptr;
 
171
       }
 
172
       /* translate addresses for all cluster nodes */
 
173
       for(cn = 0; cn < armci_nclus; cn++){
 
174
         int master = armci_clus_info[cn].master;
 
175
         offset = 0;
 
176
         /* on local cluster node use myptr directly */
 
177
         ptr = (armci_clus_me == cn) ? myptr: ptr_ref_arr[cn];
 
178
         /* compute addresses pointing to the memory regions on cluster node*/
 
179
         for(i=0; i< armci_clus_info[cn].nslave; i++){
 
180
           /* NULL if request size is 0*/
 
181
           ptr_arr[i+master] = (size_arr[i+master])? ((char*)ptr)+offset : NULL;
 
182
           offset += size_arr[i+master];
 
183
         }
 
184
       }
 
185
#   else
 
186
      /* compute addresses for local cluster node */
 
187
      offset =0;
 
188
      for(i=0; i< nproc; i++) {
 
189
        ptr_ref_arr[i] = (size_arr[i+armci_master])? ((char*)myptr)+offset : 0L;
 
190
        offset += size_arr[i+armci_master];
 
191
      }
 
192
      /* exchange addreses with all other processes */
 
193
      ptr_arr[armci_me] = (char*)ptr_ref_arr[armci_me-armci_master]; 
 
194
      armci_exchange_address(ptr_arr, armci_nproc);
 
195
      /* overwrite entries for local cluster node with ptr_ref_arr */
 
196
      bcopy((char*)ptr_ref_arr, (char*)(ptr_arr+armci_master), nproc*sizeof(void*)); 
 
197
     /*  armci_print_ptr(ptr_arr, bytes, size, myptr, offset);*/
 
198
#   endif
 
199
 
 
200
    armci_msg_barrier();
 
201
 
 
202
    /* free work arrays */
 
203
    free(ptr_ref_arr);
 
204
    free(size_arr);
 
205
    ARMCI_PR_DBG("exit",0);
 
206
 
 
207
}
 
208
 
 
209
/********************************************************************
 
210
 * Non-collective Memory Allocation on shared memory systems
 
211
\*/
 
212
void armci_shmem_memget(armci_meminfo_t *meminfo, size_t size) {
 
213
    void *myptr=NULL;
 
214
    void *armci_ptr=NULL; /* legal ARCMIptr used in ARMCI data xfer ops */
 
215
    long idlist[SHMIDLEN];
 
216
    
 
217
    /* can malloc if there is no data server process & has 1 process/node*/
 
218
#ifndef RMA_NEEDS_SHMEM
 
219
    if( armci_clus_info[armci_clus_me].nslave == 1)
 
220
       myptr = kr_malloc(size, &ctx_localmem, 0, NULL, NULL);
 
221
    else
 
222
#endif
 
223
       myptr = Create_Shared_Region(idlist+1,size,idlist);
 
224
    
 
225
    if(!myptr && size>0 )
 
226
       armci_die("armci_shmem_memget: create failed", (int)(size>>10));
 
227
    
 
228
    if(DEBUG_)
 
229
    {
 
230
       printf("%d: armci_shmem_memget: addr=%p size=%ld %ld %ld \n", armci_me,
 
231
              myptr, size, idlist[0], idlist[1]);
 
232
       fflush(stdout);
 
233
    }
 
234
 
 
235
    armci_ptr = myptr;
 
236
    
 
237
#if defined(DATA_SERVER)
 
238
    
 
239
    /* get server reference address to perform
 
240
     * remote address translation for global address space */
 
241
    if(armci_nclus>1)
 
242
    {
 
243
#   ifdef SERVER_THREAD
 
244
 
 
245
       /* data server thread runs on master process */
 
246
       if(armci_me != armci_master) {
 
247
          armci_serv_attach_req(idlist, SHMIDLEN*sizeof(long), size,
 
248
                                &armci_ptr, sizeof(void*));
 
249
       }
 
250
       
 
251
#   else
 
252
       /* ask dataserver process to attach to region and get ptr*/
 
253
       {
 
254
          extern int _armci_server_started;
 
255
          if(_armci_server_started) {
 
256
             armci_serv_attach_req(idlist, SHMIDLEN*sizeof(long), size,
 
257
                                   &armci_ptr, sizeof(void*));
 
258
          }
 
259
       }      
 
260
#   endif
 
261
    }
 
262
#endif
 
263
 
 
264
    /* fill the meminfo structure */
 
265
    meminfo->armci_addr = armci_ptr;
 
266
    meminfo->addr       = myptr;
 
267
    meminfo->size       = size;
 
268
    meminfo->cpid       = armci_me;
 
269
    bcopy(idlist, meminfo->idlist, SHMIDLEN*sizeof(long));
 
270
 
 
271
}
 
272
 
 
273
void* armci_shmem_memat(armci_meminfo_t *meminfo) {
 
274
    void *ptr=NULL;
 
275
    long size    = (long)  meminfo->size;
 
276
    long *idlist = (long*) meminfo->idlist;
 
277
  
 
278
    if(SAMECLUSNODE(meminfo->cpid))
 
279
    {
 
280
       /* Attach to the shared memory segment */
 
281
       ptr=(double*)Attach_Shared_Region(idlist+1,size,idlist[0]);
 
282
       if(!ptr)armci_die("ARMCi_Memat: could not attach", (int)(size>>10));
 
283
 
 
284
       /* CHECK: now every process in a SMP node needs to find out its offset
 
285
        * w.r.t. master - this offset is necessary to use memlock table
 
286
        */
 
287
       if(size) armci_set_mem_offset(ptr);
 
288
    }
 
289
    else
 
290
    {
 
291
       ptr = meminfo->armci_addr; /* remote address  */
 
292
    }
 
293
 
 
294
    return ptr;
 
295
}
 
296
 
 
297
void armci_shmem_memctl(armci_meminfo_t *meminfo) {
 
298
 
 
299
    /* only the creator can delete the segment */
 
300
    if(meminfo->cpid == armci_me) {
 
301
       void *ptr = meminfo->addr;
 
302
    
 
303
#ifdef RMA_NEEDS_SHMEM
 
304
       Free_Shmem_Ptr(0,0,ptr);
 
305
#else
 
306
       if(armci_clus_info[armci_clus_me].nslave>1)
 
307
          Free_Shmem_Ptr(0,0,ptr);
 
308
       else kr_free(ptr, &ctx_localmem);
 
309
#endif
 
310
    }
 
311
}
 
312
 
 
313
/****** End: Non-collective memory allocation on shared memory systems *****/
 
314
 
 
315
#ifdef MPI
 
316
/********************************************************************
 
317
 * Group Memory Allocation on shared memory systems for ARMCI Groups
 
318
\*/
 
319
void armci_shmem_malloc_group(void *ptr_arr[], armci_size_t bytes,
 
320
                              ARMCI_Group *group)
 
321
{
 
322
    void *myptr=NULL, *ptr=NULL;
 
323
    long idlist[SHMIDLEN];
 
324
    long size=0, offset=0;
 
325
    long *size_arr;
 
326
    void **ptr_ref_arr;
 
327
    int  i,cn, len;
 
328
    /* int  nproc = armci_clus_info[armci_clus_me].nslave; ? change ? */
 
329
    int grp_me, grp_nproc, grp_nclus, grp_master, grp_clus_nproc, grp_clus_me;
 
330
    armci_grp_attr_t *grp_attr=ARMCI_Group_getattr(group);
 
331
    ARMCI_PR_DBG("enter",0);
 
332
 
 
333
    /* Get the group info: group size & group rank */
 
334
    ARMCI_Group_size(group, &grp_nproc);
 
335
    ARMCI_Group_rank(group, &grp_me);
 
336
    if(grp_me == MPI_UNDEFINED) { /* check if the process is in this group */
 
337
       armci_die("armci_malloc_group: process is not a member in this group",
 
338
                 armci_me);
 
339
    }
 
340
 
 
341
    grp_nclus      = grp_attr->grp_nclus;
 
342
    grp_clus_me    = grp_attr->grp_clus_me;
 
343
    grp_master     = grp_attr->grp_clus_info[grp_clus_me].master;
 
344
    grp_clus_nproc = grp_attr->grp_clus_info[grp_clus_me].nslave;
 
345
 
 
346
    bzero((char*)ptr_arr,grp_nproc*sizeof(void*));
 
347
 
 
348
    /* allocate work arrays */
 
349
    size_arr = (long*)calloc(grp_nproc,sizeof(long));
 
350
    if(!size_arr)armci_die("armci_malloc_group:calloc failed",grp_nproc);
 
351
 
 
352
    /* allocate arrays for cluster address translations */
 
353
#   if defined(DATA_SERVER)
 
354
        len = grp_nclus;
 
355
#   else
 
356
        len = grp_clus_nproc;
 
357
#   endif
 
358
 
 
359
    ptr_ref_arr = calloc(len,sizeof(void*)); /* must be zero */
 
360
    if(!ptr_ref_arr)armci_die("armci_malloc_group:calloc 2 failed",len);
 
361
 
 
362
    /* combine all memory requests into size_arr  */
 
363
    size_arr[grp_me] = bytes;
 
364
    armci_msg_group_gop_scope(SCOPE_ALL, size_arr, grp_nproc, "+", ARMCI_LONG,
 
365
                              group);
 
366
 
 
367
    /* determine aggregate request size on the cluster node */
 
368
    for(i=0, size=0; i< grp_clus_nproc; i++) size += size_arr[i+grp_master];
 
369
 
 
370
    /* master process creates shmem region and then others attach to it */
 
371
    if(grp_me == grp_master ){
 
372
 
 
373
 
 
374
       /* can malloc if there is no data server process and has 1 process/node*/
 
375
#     ifndef RMA_NEEDS_SHMEM
 
376
       if( armci_clus_info[armci_clus_me].nslave == 1)
 
377
         myptr = kr_malloc(size, &ctx_localmem, 0, NULL, NULL);
 
378
       else
 
379
#     endif
 
380
         myptr = Create_Shared_Region(idlist+1,size,idlist);
 
381
       if(!myptr && size>0 )
 
382
         armci_die("armci_malloc_group: could not create", (int)(size>>10));
 
383
 
 
384
       /* place its address at begining of attached region for others to see */
 
385
       if(size)armci_master_exp_attached_ptr(myptr);
 
386
 
 
387
       if(DEBUG_){
 
388
         printf("%d:armci_malloc_group addr mptr=%p ref=%p size=%ld %ld %ld \n",armci_me,myptr,*(void**)myptr, size,idlist[0],idlist[1]);
 
389
         fflush(stdout);
 
390
       }
 
391
    }
 
392
 
 
393
    /* broadcast shmem id to other processes (in the same group) on the 
 
394
       same cluster node */
 
395
    armci_grp_clus_brdcst(idlist, SHMIDLEN*sizeof(long), grp_master, 
 
396
                          grp_clus_nproc, group);
 
397
 
 
398
    if(grp_me != grp_master){
 
399
       myptr=(double*)Attach_Shared_Region(idlist+1,size,idlist[0]);
 
400
       if(!myptr)armci_die("armci_malloc_group: could not attach", (int)(size>>10));
 
401
 
 
402
       /* now every process in a SMP node needs to find out its offset
 
403
        * w.r.t. master - this offset is necessary to use memlock table
 
404
        */
 
405
       if(size) armci_set_mem_offset(myptr);
 
406
       if(DEBUG_){
 
407
          printf("%d:armci_malloc_group attached addr mptr=%p ref=%p size=%ld\n",
 
408
                 armci_me,myptr, *(void**)myptr,size); fflush(stdout);
 
409
       }
 
410
    }
 
411
    
 
412
#   if defined(DATA_SERVER)
 
413
 
 
414
    /* get server reference address for every cluster node in the group 
 
415
     * to perform remote address translation for global address space */
 
416
    if(grp_nclus>1){
 
417
       if(grp_me == grp_master){
 
418
 
 
419
#            ifdef SERVER_THREAD
 
420
 
 
421
          /* data server thread runs on master process */
 
422
          if(ARMCI_Absolute_id(group,grp_master)!=armci_master){
 
423
            /*printf("\n%d: grp_master=%d %ld %ld \n",armci_me,ARMCI_Absolute_id(group,grp_master),idlist[0],idlist[1]);*/
 
424
            armci_serv_attach_req(idlist, SHMIDLEN*sizeof(long), size,
 
425
                                  &ptr, sizeof(void*));
 
426
            ptr_ref_arr[grp_clus_me]= ptr; /* from server*/
 
427
          }
 
428
          else
 
429
            ptr_ref_arr[grp_clus_me]=myptr;
 
430
          
 
431
#            else
 
432
          /* ask data server process to attach to the region and get ptr */
 
433
          {
 
434
             extern int _armci_server_started;
 
435
             if(_armci_server_started) {
 
436
                armci_serv_attach_req(idlist, SHMIDLEN*sizeof(long), size,
 
437
                                      &ptr, sizeof(void*));
 
438
                ptr_ref_arr[grp_clus_me]= ptr; /* from server*/
 
439
             }
 
440
             else /* server not yet started */
 
441
                ptr_ref_arr[grp_clus_me]=myptr;
 
442
          }
 
443
 
 
444
          if(DEBUG_){
 
445
             printf("%d:addresses server=%p myptr=%p\n",grp_me,ptr,myptr);
 
446
               fflush(stdout);
 
447
          }
 
448
#            endif
 
449
       }
 
450
       /* exchange ref addr of shared memory region on every cluster node*/
 
451
       {
 
452
          int ratio = sizeof(void*)/sizeof(int);
 
453
          if(DEBUG_)printf("%d: exchanging %ld ratio=%d\n",armci_me,
 
454
                           (long)ptr_arr[grp_me], ratio);
 
455
          armci_msg_group_gop_scope(SCOPE_ALL, ptr_ref_arr, grp_nclus*ratio,
 
456
                                    "+", ARMCI_INT, group);
 
457
        # ifdef ARMCI_REGISTER_SHMEM
 
458
          armci_register_shmem_grp(myptr,size,idlist+1,idlist[0],ptr_ref_arr[armci_clus_me],group);
 
459
        # endif
 
460
       }
 
461
    }else {
 
462
       
 
463
       ptr_ref_arr[grp_master] = myptr;
 
464
       
 
465
    }
 
466
    
 
467
    /* translate addresses for all cluster nodes */
 
468
    for(cn = 0; cn < grp_nclus; cn++){
 
469
       
 
470
       int master = grp_attr->grp_clus_info[cn].master;
 
471
       offset = 0;
 
472
 
 
473
       /* on local cluster node use myptr directly */
 
474
       ptr = (grp_clus_me == cn) ? myptr: ptr_ref_arr[cn];
 
475
 
 
476
       /* compute addresses pointing to the memory regions on cluster node*/
 
477
       for(i=0; i< grp_attr->grp_clus_info[cn].nslave; i++){
 
478
 
 
479
          /* NULL if request size is 0*/
 
480
          ptr_arr[i+master] =(size_arr[i+master])? ((char*)ptr)+offset: NULL;
 
481
            offset += size_arr[i+master];
 
482
       }
 
483
    }
 
484
 
 
485
#   else
 
486
 
 
487
    /* compute addresses for local cluster node */
 
488
    offset =0;
 
489
    for(i=0; i< grp_clus_nproc; i++) {
 
490
       
 
491
       ptr_ref_arr[i] = (size_arr[i+grp_master])? ((char*)myptr)+offset : 0L;
 
492
       offset += size_arr[i+grp_master];
 
493
       
 
494
    }
 
495
    
 
496
    /* exchange addreses with all other processes */
 
497
    ptr_arr[grp_me] = (char*)ptr_ref_arr[grp_me-grp_master]; 
 
498
    armci_exchange_address_grp(ptr_arr, grp_nproc, group);
 
499
 
 
500
    /* overwrite entries for local cluster node with ptr_ref_arr */
 
501
    bcopy((char*)ptr_ref_arr, (char*)(ptr_arr+grp_master), grp_clus_nproc*sizeof(void*)); 
 
502
     
 
503
#   endif
 
504
 
 
505
    /*  armci_print_ptr(ptr_arr, bytes, size, myptr, offset);*/
 
506
       
 
507
    armci_msg_group_barrier(group);
 
508
 
 
509
    /* free work arrays */
 
510
    free(ptr_ref_arr);
 
511
    free(size_arr);
 
512
    ARMCI_PR_DBG("exit",0);
 
513
}
 
514
#endif /* ifdef MPI */
 
515
 
 
516
#else
 
517
 
 
518
void armci_shmem_malloc(void* ptr_arr[], int bytes)
 
519
{
 
520
  armci_die("armci_shmem_malloc should never be called on this system",0);
 
521
}
 
522
void armci_shmem_memget(armci_meminfo_t *meminfo, size_t size) {
 
523
  armci_die("armci_shmem_memget should never be called on this system",0);
 
524
}
 
525
void* armci_shmem_memat(armci_meminfo_t *meminfo) {
 
526
  armci_die("armci_shmem_memat should never be called on this system",0);
 
527
}
 
528
void armci_shmem_memctl(armci_meminfo_t *meminfo) {
 
529
  armci_die("armci_shmem_memctl should never be called on this system",0);  
 
530
}
 
531
# ifdef MPI
 
532
  void armci_shmem_malloc_group(void *ptr_arr[], armci_size_t bytes,
 
533
                                ARMCI_Group *group) {
 
534
      armci_die("armci_shmem_malloc_group should never be called on this system",0);
 
535
  }
 
536
# endif
 
537
 
 
538
#endif
 
539
 
 
540
 
 
541
/* public constructor to initialize the kr_malloc context */
 
542
void armci_krmalloc_init_localmem() {
 
543
#if defined(ALLOW_PIN)
 
544
    kr_malloc_init(0, 0, 0, reg_malloc, 0, &ctx_localmem);
 
545
    kr_malloc_init(0, 0, 0, malloc, 0, &ctx_mlocalmem);
 
546
    ctx_mlocalmem.ctx_type = KR_CTX_LOCALMEM;
 
547
#elif defined(CRAY_SHMEM) && defined(CRAY_XT)
 
548
#   ifdef CATAMOUNT
 
549
    int units_avail = (cnos_shmem_size() - 1024 * 1024) / SHM_UNIT;
 
550
#   else
 
551
    extern size_t get_xt_heapsize();
 
552
    int units_avail = (get_xt_heapsize() - 1024 * 1024) / SHM_UNIT;
 
553
#   endif
 
554
 
 
555
    if(DEBUG_) 
 
556
    {
 
557
       fprintf(stderr,"%d:krmalloc_init_localmem: symheap=%llu,units(%d)=%d\n",
 
558
               armci_me, SHM_UNIT*units_avail, SHM_UNIT, units_avail);
 
559
    }
 
560
    kr_malloc_init(SHM_UNIT, units_avail, units_avail, shmalloc, 0,
 
561
                   &ctx_localmem);
 
562
    armci_shmalloc_exchange_offsets(&ctx_localmem);
 
563
#else
 
564
 
 
565
    kr_malloc_init(0, 0, 0, malloc, 0, &ctx_localmem);
 
566
 
 
567
#endif
 
568
 
 
569
    ctx_localmem.ctx_type = KR_CTX_LOCALMEM;
 
570
}
 
571
 
 
572
/**
 
573
 * Local Memory Allocation and Free
 
574
 */
 
575
void *PARMCI_Malloc_local(armci_size_t bytes) {
 
576
    void *rptr;
 
577
    ARMCI_PR_DBG("enter",0);
 
578
    ARMCI_PR_DBG("exit",0);
 
579
    rptr = (void *)kr_malloc((size_t)bytes, &ctx_localmem, 0, NULL, NULL);
 
580
    //printf("\n%d:%s:%d:%p\n",armci_me,FUNCTION_NAME,bytes,rptr);
 
581
    return rptr;
 
582
}
 
583
 
 
584
int PARMCI_Free_local(void *ptr) {
 
585
    ARMCI_PR_DBG("enter",0);
 
586
    kr_free((char *)ptr, &ctx_localmem);
 
587
    ARMCI_PR_DBG("exit",0);
 
588
    return 0;
 
589
}
 
590
 
 
591
 
 
592
/*\ Collective Memory Allocation
 
593
 *  returns array of pointers to blocks of memory allocated by everybody
 
594
 *  Note: as the same shared memory region can be mapped at different locations
 
595
 *        in each process address space, the array might hold different values
 
596
 *        on every process. However, the addresses are legitimate
 
597
 *        and can be used in the ARMCI data transfer operations.
 
598
 *        ptr_arr[nproc]
 
599
\*/
 
600
int PARMCI_Malloc(void *ptr_arr[], armci_size_t bytes)
 
601
{
 
602
    void *ptr;
 
603
    char *new_base;
 
604
    size_t new_size=0;
 
605
    ARMCI_PR_DBG("enter",0);
 
606
    if(DEBUG_){ 
 
607
       fprintf(stderr,"%d bytes in armci_malloc %d\n",armci_me, (int)bytes);
 
608
       fflush(stderr);
 
609
       armci_msg_barrier();
 
610
    }
 
611
 
 
612
#  ifdef USE_MALLOC
 
613
    if(armci_nproc == 1) {
 
614
      ptr = kr_malloc((size_t) bytes, &ctx_localmem, 0, NULL, NULL);
 
615
      if(bytes) if(!ptr) armci_die("armci_malloc:malloc 1 failed",(int)bytes);
 
616
      ptr_arr[armci_me] = ptr;
 
617
      ARMCI_PR_DBG("exit",0);
 
618
      return (0);
 
619
    }
 
620
#  endif
 
621
 
 
622
   // static int one_time = 0;
 
623
 
 
624
    if( ARMCI_Uses_shm() ) {
 
625
    //  if(one_time++ == 0 && armci_me==0) printf("%d: ARMCI_Uses_shm = true\n",armci_me);
 
626
      armci_shmem_malloc(ptr_arr,bytes);
 
627
    } else {
 
628
      /* on distributed-memory systems just malloc & collect all addresses */
 
629
      ptr = kr_malloc(bytes, &ctx_localmem, 1, &new_base, &new_size);
 
630
      if(bytes) if(!ptr) armci_die("armci_malloc:malloc 2 failed",bytes);
 
631
 
 
632
      bzero((char*)ptr_arr,armci_nproc*sizeof(void*));
 
633
      ptr_arr[armci_me] = ptr;
 
634
      
 
635
      /* now combine individual addresses into a single array */
 
636
      armci_exchange_address(ptr_arr, armci_nproc);
 
637
    # ifdef ARMCI_REGISTER_SHMEM
 
638
      if(new_size)
 
639
        armci_register_shmem(new_base,new_size,NULL,0,new_base);
 
640
      else
 
641
        armci_register_shmem(ptr,bytes,NULL,0,ptr);
 
642
    # endif
 
643
    }
 
644
    ARMCI_PR_DBG("exit",0);
 
645
    //printf("\n%d:%s:%d:%p\n",armci_me,FUNCTION_NAME,bytes,ptr_arr[armci_me]);
 
646
    return(0);
 
647
}
 
648
 
 
649
 
 
650
 
 
651
/*\ shared memory is released to kr_malloc only on process 0
 
652
 *  with data server malloc cannot be used
 
653
\*/
 
654
int PARMCI_Free(void *ptr)
 
655
{
 
656
    ARMCI_PR_DBG("enter",0);
 
657
    if(!ptr)return 1;
 
658
 
 
659
#    if (defined(SYSV) || defined(WIN32) || defined(MMAP)) && !defined(NO_SHM)
 
660
#       ifdef USE_MALLOC
 
661
          if(armci_nproc > 1)
 
662
#       endif
 
663
             if(ARMCI_Uses_shm()){
 
664
                if(armci_me==armci_master){
 
665
#               ifdef RMA_NEEDS_SHMEM
 
666
                   Free_Shmem_Ptr(0,0,ptr);
 
667
#               else
 
668
                   if(armci_clus_info[armci_clus_me].nslave>1)
 
669
                      Free_Shmem_Ptr(0,0,ptr);
 
670
                   else kr_free(ptr, &ctx_localmem);
 
671
#               endif
 
672
                }
 
673
                ptr = NULL;
 
674
                return 0;
 
675
             }
 
676
#    endif
 
677
          kr_free(ptr, &ctx_localmem);
 
678
    //armci_unregister_shmem(ptr,0);
 
679
    ptr = NULL;
 
680
    ARMCI_PR_DBG("exit",0);
 
681
    return 0;
 
682
}
 
683
 
 
684
 
 
685
int ARMCI_Uses_shm()
 
686
{
 
687
    int uses=0;
 
688
 
 
689
#if (defined(SYSV) || defined(WIN32) || defined(MMAP) ||defined(HITACHI)) \
 
690
    && !defined(NO_SHM)
 
691
#   ifdef RMA_NEEDS_SHMEM
 
692
      if(armci_nproc >1) uses= 1; /* always unless serial mode */
 
693
#   else
 
694
      if(armci_nproc != armci_nclus)uses= 1; /* only when > 1 node used */
 
695
#   endif
 
696
#endif
 
697
    if(DEBUG_) fprintf(stderr,"%d:uses shmem %d\n",armci_me, uses);
 
698
    return uses;
 
699
}
 
700
#ifdef MPI
 
701
 
 
702
int ARMCI_Uses_shm_grp(ARMCI_Group *group) 
 
703
{    
 
704
    int uses=0, grp_me, grp_nproc, grp_nclus;
 
705
    ARMCI_PR_DBG("enter",0);
 
706
    armci_grp_attr_t *grp_attr=ARMCI_Group_getattr(group);
 
707
 
 
708
    ARMCI_Group_size(group, &grp_nproc);
 
709
    ARMCI_Group_rank(group, &grp_me);
 
710
    grp_nclus = grp_attr->grp_nclus;
 
711
    
 
712
#if (defined(SYSV) || defined(WIN32) || defined(MMAP) ||defined(HITACHI)) \
 
713
    && !defined(NO_SHM)
 
714
#   ifdef RMA_NEEDS_SHMEM
 
715
      if(grp_nproc >1) uses= 1; /* always unless serial mode */
 
716
#   else
 
717
      if(grp_nproc != grp_nclus)uses= 1; /* only when > 1 node used */
 
718
#   endif
 
719
#endif
 
720
    if(DEBUG_) fprintf(stderr,"%d (grp_id=%d):uses shmem %d\n",armci_me, grp_me, uses);
 
721
    ARMCI_PR_DBG("exit",0);
 
722
    return uses;
 
723
}
 
724
 
 
725
/*\ ************** Begin Group Collective Memory Allocation ******************
 
726
 *  returns array of pointers to blocks of memory allocated by everybody
 
727
 *  Note: as the same shared memory region can be mapped at different locations
 
728
 *        in each process address space, the array might hold different values
 
729
 *        on every process. However, the addresses are legitimate
 
730
 *        and can be used in the ARMCI data transfer operations.
 
731
 *        ptr_arr[nproc]
 
732
\*/
 
733
int ARMCI_Malloc_group(void *ptr_arr[], armci_size_t bytes,
 
734
                       ARMCI_Group *group)
 
735
{
 
736
    void *ptr;
 
737
    int grp_me, grp_nproc;
 
738
    ARMCI_PR_DBG("enter",0);
 
739
    ARMCI_Group_size(group, &grp_nproc);
 
740
    ARMCI_Group_rank(group, &grp_me);
 
741
    if(DEBUG_)fprintf(stderr,"%d (grp_id=%d) bytes in armci_malloc_group %d\n",
 
742
                      armci_me, grp_me, (int)bytes);
 
743
#ifdef USE_MALLOC
 
744
    if(grp_nproc == 1) {
 
745
       ptr = kr_malloc((size_t) bytes, &ctx_localmem, 0, NULL, NULL);
 
746
       if(bytes) if(!ptr) armci_die("armci_malloc_group:malloc 1 failed",(int)bytes);
 
747
       ptr_arr[grp_me] = ptr;
 
748
       ARMCI_PR_DBG("exit",0);
 
749
       return (0);
 
750
    }
 
751
#endif
 
752
    
 
753
    if( ARMCI_Uses_shm_grp(group) ) {
 
754
#      ifdef SGIALTIX
 
755
          armci_altix_shm_malloc_group(ptr_arr,bytes,group);
 
756
#      else   
 
757
          armci_shmem_malloc_group(ptr_arr,bytes,group);
 
758
#      endif
 
759
    }
 
760
    else {
 
761
       void *new_base=NULL;
 
762
       size_t new_size=NULL;
 
763
       ptr = kr_malloc(bytes, &ctx_localmem, 1, &new_base, &new_size);
 
764
       if(bytes) if(!ptr) armci_die("armci_malloc:malloc 2 failed",bytes);
 
765
       
 
766
       bzero((char*)ptr_arr,grp_nproc*sizeof(void*));
 
767
       ptr_arr[grp_me] = ptr;
 
768
       
 
769
       /* now combine individual addresses into a single array */
 
770
       armci_exchange_address_grp(ptr_arr, grp_nproc, group);
 
771
      
 
772
    }
 
773
    ARMCI_PR_DBG("exit",0);
 
774
    return(0);
 
775
}
 
776
 
 
777
 
 
778
/*\ shared memory is released to kr_malloc only on process 0
 
779
 *  with data server malloc cannot be used
 
780
 \*/
 
781
int ARMCI_Free_group(void *ptr, ARMCI_Group *group)
 
782
{
 
783
    int grp_me, grp_nproc, grp_master, grp_clus_me;
 
784
    armci_grp_attr_t *grp_attr=ARMCI_Group_getattr(group);
 
785
    ARMCI_PR_DBG("enter",0);
 
786
    
 
787
    if(!ptr)return 1;
 
788
 
 
789
    ARMCI_Group_size(group, &grp_nproc);
 
790
    ARMCI_Group_rank(group, &grp_me);
 
791
    if(grp_me == MPI_UNDEFINED) { /* check if the process is in this group */
 
792
       armci_die("armci_malloc_group: process is not a member in this group",
 
793
                 armci_me);
 
794
    }
 
795
    /* get the group cluster info */
 
796
    grp_clus_me    = grp_attr->grp_clus_me;
 
797
    grp_master     = grp_attr->grp_clus_info[grp_clus_me].master;
 
798
 
 
799
#   if (defined(SYSV) || defined(WIN32) || defined(MMAP)) && !defined(NO_SHM)
 
800
#      ifdef USE_MALLOC
 
801
         if(grp_nproc > 1)
 
802
#      endif
 
803
       if(ARMCI_Uses_shm_grp(group)){
 
804
          if(grp_me == grp_master) {
 
805
#            ifdef RMA_NEEDS_SHMEM
 
806
             Free_Shmem_Ptr(0,0,ptr);
 
807
#            else
 
808
             if(armci_clus_info[armci_clus_me].nslave>1) Free_Shmem_Ptr(0,0,ptr);
 
809
             else kr_free(ptr, &ctx_localmem);
 
810
#            endif
 
811
          }
 
812
          ptr = NULL;
 
813
          ARMCI_PR_DBG("exit",0);
 
814
          return 0;
 
815
       }
 
816
#   endif
 
817
    kr_free(ptr, &ctx_localmem);
 
818
 
 
819
    ptr = NULL;
 
820
    ARMCI_PR_DBG("exit",0);
 
821
    return 0;
 
822
}
 
823
/* ***************** End Group Collective Memory Allocation ******************/
 
824
 
 
825
/* ************** Begin Non-Collective Memory Allocation ******************
 
826
 * Prototype similar to SysV shared memory.
 
827
 */
 
828
 
 
829
/**
 
830
 * CHECK: On Altix we are forced to use SysV as shmalloc is collective. We
 
831
 * may use a preallocated shmalloc memory, however, it may NOT still solve
 
832
 * our problem...
 
833
 * NOTE: "int memflg" option for future optimiztions.
 
834
 */
 
835
void PARMCI_Memget(size_t bytes, armci_meminfo_t *meminfo, int memflg) {
 
836
 
 
837
    void *myptr=NULL;
 
838
    void *armci_ptr=NULL; /* legal ARCMI ptr used in ARMCI data xfer ops*/
 
839
    size_t size = bytes;
 
840
    
 
841
    if(size<=0) armci_die("ARMCI_Memget: size must be > 0", (int)size);
 
842
    if(meminfo==NULL) armci_die("ARMCI_Memget: Invalid arg #2 (NULL ptr)",0);
 
843
    if(memflg!=0) armci_die("ARMCI_Memget: Invalid memflg", memflg);
 
844
 
 
845
    if( !ARMCI_Uses_shm() )
 
846
    {
 
847
       armci_ptr = myptr = kr_malloc(size, &ctx_localmem, 0, NULL, NULL);
 
848
       if(size) if(!myptr) armci_die("ARMCI_Memget failed", (int)size);
 
849
 
 
850
       /* fill the meminfo structure */
 
851
       meminfo->armci_addr = armci_ptr;
 
852
       meminfo->addr       = myptr;
 
853
       meminfo->size       = size;
 
854
       meminfo->cpid       = armci_me;
 
855
       /* meminfo->attr       = NULL; */
 
856
    }
 
857
    else
 
858
    {
 
859
       armci_shmem_memget(meminfo, size);
 
860
    }
 
861
    
 
862
    if(DEBUG_){
 
863
       printf("%d: ARMCI_Memget: addresses server=%p myptr=%p bytes=%ld\n",
 
864
              armci_me, meminfo->armci_addr, meminfo->addr, bytes);
 
865
       fflush(stdout);
 
866
    }    
 
867
}
 
868
 
 
869
void* PARMCI_Memat(armci_meminfo_t *meminfo, long offset) {
 
870
    void *ptr=NULL;
 
871
    
 
872
    if(meminfo==NULL) armci_die("ARMCI_Memget: Invalid arg #2 (NULL ptr)",0);
 
873
    if(offset!=0) armci_die("ARMCI_Memget: Invalid offset", offset);
 
874
 
 
875
    if(meminfo->cpid==armci_me) { ptr = meminfo->addr; return ptr; }
 
876
 
 
877
    if( !ARMCI_Uses_shm())
 
878
    {
 
879
       ptr = meminfo->addr;
 
880
    }
 
881
    else
 
882
    {
 
883
       ptr = armci_shmem_memat(meminfo);
 
884
    }
 
885
    
 
886
    if(DEBUG_)
 
887
    {
 
888
       printf("%d:ARMCI_Memat: attached addr mptr=%p size=%ld\n",
 
889
              armci_me, ptr, meminfo->size); fflush(stdout);
 
890
    }
 
891
    
 
892
    return ptr;
 
893
}
 
894
 
 
895
void ARMCI_Memdt(armci_meminfo_t *meminfo, long offset) {
 
896
  /**
 
897
   * Do nothing. May be we need to have reference counting in future. This
 
898
   * is to avoid the case of dangling pointers when the creator of shm
 
899
   * segment calls Memctl and other processes are still attached to this
 
900
   * segment
 
901
   */
 
902
}
 
903
 
 
904
void ARMCI_Memctl(armci_meminfo_t *meminfo) {
 
905
 
 
906
    if(meminfo==NULL) armci_die("ARMCI_Memget: Invalid arg #2 (NULL ptr)",0);
 
907
 
 
908
    /* only the creator can delete the segment */
 
909
    if(meminfo->cpid == armci_me)
 
910
    {
 
911
       if( !ARMCI_Uses_shm() )
 
912
       {
 
913
          void *ptr = meminfo->addr;
 
914
          kr_free(ptr, &ctx_localmem);
 
915
       }
 
916
       else
 
917
       {
 
918
          armci_shmem_memctl(meminfo);
 
919
       }
 
920
    }
 
921
 
 
922
    meminfo->addr       = NULL;
 
923
    meminfo->armci_addr = NULL;
 
924
    /* if(meminfo->attr!=NULL) free(meminfo->attr); */
 
925
}
 
926
 
 
927
/* ***************** End Non-Collective Memory Allocation ******************/
 
928
 
 
929
#endif
 
930
#endif