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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-1/armci/src/collectives/message.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: message.c,v 1.58.6.4 2007-04-24 10:08:26 vinod Exp $ */
6
 
#if defined(BGML)
7
 
# include "bgml.h"
8
 
#elif defined(PVM)
9
 
#   include <pvm3.h>
10
 
#elif defined(TCGMSG)
11
 
#   include <tcgmsg.h>
12
 
#else
13
 
#   ifndef MPI
14
 
#      define MPI
15
 
#   endif
16
 
#   include <mpi.h>
17
 
#endif
18
 
#include "message.h"
19
 
#include "armcip.h"
20
 
#include "copy.h"
21
 
#if HAVE_STDIO_H
22
 
#   include <stdio.h>
23
 
#endif
24
 
#if HAVE_ASSERT_H
25
 
#   include <assert.h>
26
 
#endif
27
 
#ifdef _POSIX_PRIORITY_SCHEDULING
28
 
#ifndef HITACHI
29
 
#  include <sched.h>
30
 
#endif
31
 
#endif
32
 
#include "armci.h"
33
 
#include "acc.h"
34
 
 
35
 
#define DEBUG_ 0
36
 
#if defined(SYSV) || defined(MMAP) ||defined (WIN32)
37
 
#    include "shmem.h"
38
 
#endif
39
 
 
40
 
/* global operations are use buffer size of BUF_SIZE doubles */ 
41
 
#define BUF_SIZE  (4*2048)
42
 
#define INFO_BUF_SIZE  (BUF_SIZE*sizeof(BUF_SIZE) - sizeof(double))
43
 
#undef EMPTY
44
 
#define EMPTY 0
45
 
#define FULL 1
46
 
 
47
 
static double *work=NULL;
48
 
static long *lwork = NULL;
49
 
static long long *llwork = NULL;
50
 
static int *iwork = NULL;
51
 
static float *fwork = NULL;
52
 
static int _armci_gop_init=0;   /* tells us if we have a buffers allocated  */
53
 
static int _armci_gop_shmem =0; /* tells us to use shared memory for gops */
54
 
extern void armci_util_wait_int(volatile int *, int , int );
55
 
static int empty=EMPTY,full=FULL;
56
 
#if !defined(SGIALTIX) && defined(SYSV) || defined(MMAP) || defined(WIN32)
57
 
static void **ptr_arr=NULL;
58
 
#endif
59
 
 
60
 
typedef struct {
61
 
        union {
62
 
           volatile int flag;
63
 
           double dummy[16];
64
 
        }a;
65
 
        union {
66
 
           volatile int flag;
67
 
           double dummy[16];
68
 
        }b;
69
 
        double array[BUF_SIZE];
70
 
} bufstruct;
71
 
 
72
 
static bufstruct *_gop_buffer; 
73
 
 
74
 
#define GOP_BUF(p)  (_gop_buffer+((p)-armci_master))
75
 
 
76
 
/*\ macro to set a flag includes mem barrier to assure that flag is not set 
77
 
 *  before any outstanding writes complete 
78
 
\*/
79
 
#ifdef NEED_MEM_SYNC
80
 
#  ifdef AIX
81
 
#    define SET_SHM_FLAG(_flg,_val) _clear_lock((int *)(_flg),_val);
82
 
#  elif defined(NEC)
83
 
#    define SET_SHM_FLAG(_flg,_val) MEM_FENCE; *(_flg)=(_val)
84
 
#  elif defined(__ia64)
85
 
#    if defined(__GNUC__) && !defined (__INTEL_COMPILER)
86
 
#       define SET_SHM_FLAG(_flg,_val)\
87
 
            __asm__ __volatile__ ("mf" ::: "memory"); *(_flg)=(_val)
88
 
#    else /* Intel Compiler */
89
 
        extern void _armci_ia64_mb();
90
 
#       define SET_SHM_FLAG(_flg,_val)\
91
 
            _armci_ia64_mb(); *(_flg)=(_val);
92
 
#    endif
93
 
#  elif defined(MACX)
94
 
#    if defined(__GNUC__)
95
 
#    define SET_SHM_FLAG(_flg,_val)\
96
 
           *(_flg)=(_val);__asm__ __volatile__ ("isync" ::: "memory")
97
 
#    endif
98
 
#  endif
99
 
#endif
100
 
 
101
 
#ifndef SET_SHM_FLAG
102
 
#   define SET_SHM_FLAG(_flg,_val) *(_flg)=_val;
103
 
#endif
104
 
 
105
 
 
106
 
 
107
 
/*\
108
 
 *  Variables/structures for use in Barrier and for Binomial tree
109
 
\*/
110
 
#if HAVE_MATH_H
111
 
#   include <math.h>
112
 
#endif
113
 
int barr_switch;
114
 
static int LnB=0,powof2nodes,Lp2;
115
 
typedef struct {
116
 
        volatile int flag1;
117
 
        double dum[16];
118
 
        volatile int flag2;
119
 
} barrier_struct;
120
 
barrier_struct *_bar_buff;
121
 
#define BAR_BUF(p) (_bar_buff+((p)))
122
 
void **barr_snd_ptr,**barr_rcv_ptr;
123
 
int _armci_barrier_init=0;
124
 
int _armci_barrier_shmem=0;
125
 
 
126
 
 
127
 
/*\
128
 
 * Tree generation code
129
 
\*/
130
 
static void _dfs_bintree_parse(int *idlist, int index, int max, int *result)
131
 
{
132
 
int left = (int)2*index+1;
133
 
int right = (int) 2*index+2;
134
 
static int pos=0;
135
 
int r_end,l_end;
136
 
   l_end=pos++;
137
 
   result[pos++]=idlist[index];
138
 
   if(left<max)
139
 
     _dfs_bintree_parse(idlist,left,max,result);
140
 
   r_end=pos++;
141
 
   result[l_end]=r_end;
142
 
   if(right<max)
143
 
     _dfs_bintree_parse(idlist,right,max,result);
144
 
   result[r_end]=pos;
145
 
   result[pos++]=idlist[index];
146
 
}
147
 
static int tree_unique_id=0;
148
 
int armci_msg_generate_tree(int *idlist,int idlen,int *id_tree,int TREE)
149
 
{
150
 
   
151
 
    /*for now everything is binary tree*/
152
 
    _dfs_bintree_parse(idlist,0,idlen,id_tree);
153
 
    return tree_unique_id++;
154
 
}
155
 
 
156
 
/*\
157
 
 *  *************************************************************
158
 
\*/
159
 
#ifdef CRAY
160
 
char *mp_group_name = (char *)NULL;
161
 
#else
162
 
char *mp_group_name = "mp_working_group";
163
 
#endif
164
 
 
165
 
 
166
 
static void _allocate_mem_for_work(){
167
 
    work = (double *)malloc(sizeof(double)*BUF_SIZE);
168
 
    if(!work)armci_die("malloc in _allocate_mem_for_work failed",0);
169
 
    lwork = (long *)work; iwork = (int *)work; fwork = (float *)work;
170
 
    llwork = (long long *)work;
171
 
}
172
 
 
173
 
 
174
 
static void _deallocate_mem_for_work(){
175
 
    if (work) free(work);
176
 
    work = NULL; lwork = NULL; iwork = NULL; fwork = NULL; llwork = NULL;
177
 
}
178
 
 
179
 
 
180
 
/*\ allocate and initialize buffers used for collective communication
181
 
\*/
182
 
void armci_msg_gop_init()
183
 
{
184
 
/*work was a static global array of doubles. It has been changed to get
185
 
  memory from malloc because of a problem with cc on SV1
186
 
*/
187
 
    if(work==NULL)_allocate_mem_for_work();
188
 
#if !defined(SGIALTIX) && defined(SYSV) || defined(MMAP) || defined(WIN32)
189
 
    if(ARMCI_Uses_shm()){
190
 
       char *tmp;
191
 
       double *work;
192
 
       int size = sizeof(bufstruct);
193
 
       int bytes = size * armci_clus_info[armci_clus_me].nslave;
194
 
#ifdef LAPI
195
 
       void armci_msg_barr_init();
196
 
       armci_msg_barr_init();
197
 
#endif
198
 
       bytes += size*2; /* extra for brdcst */
199
 
 
200
 
       ptr_arr = (void**)malloc(armci_nproc*sizeof(void*));
201
 
       if(armci_me==armci_master) bytes += 128;
202
 
       else bytes=0;
203
 
       PARMCI_Malloc(ptr_arr, bytes);
204
 
       tmp = (char*)ptr_arr[armci_master];
205
 
 
206
 
       if(DEBUG_){
207
 
          printf("%d: allocate gop buffer %p %d\n",armci_me,tmp,bytes);
208
 
          fflush(stdout);
209
 
       }
210
 
 
211
 
       if(!tmp) armci_die("armci_msg_init: shm malloc failed\n",size);
212
 
       _gop_buffer = ( bufstruct *) tmp;
213
 
       work = GOP_BUF(armci_me)->array; /* each process finds its place */
214
 
       GOP_BUF(armci_me)->a.flag=EMPTY;   /* initially buffer is empty */
215
 
       GOP_BUF(armci_me)->b.flag=EMPTY;  /* initially buffer is empty */
216
 
       if(armci_me == armci_master ){
217
 
          GOP_BUF(armci_clus_last+1)->a.flag=EMPTY;/*initially buffer is empty*/
218
 
          GOP_BUF(armci_clus_last+2)->a.flag=EMPTY;/*initially buffer is empty*/
219
 
          GOP_BUF(armci_clus_last+1)->b.flag=EMPTY;/*initially buffer is empty*/
220
 
          GOP_BUF(armci_clus_last+2)->b.flag=EMPTY;/*initially buffer is empty*/
221
 
       }
222
 
       _armci_gop_shmem = 1;
223
 
     }
224
 
#endif
225
 
     /*stuff needed for barrier and binomial bcast/reduce*/
226
 
#ifdef LAPI
227
 
     if(!_armci_barrier_shmem){
228
 
       int size = 2*sizeof(int);
229
 
       /*allocate memory to send/rcv data*/
230
 
       barr_snd_ptr = (void **)malloc(sizeof(void *)*armci_nproc);
231
 
       barr_rcv_ptr = (void **)malloc(sizeof(void *)*armci_nproc);
232
 
 
233
 
       if(PARMCI_Malloc(barr_snd_ptr,size))armci_die("malloc barrinit failed",0);
234
 
       if(PARMCI_Malloc(barr_rcv_ptr,size))armci_die("malloc barrinit failed",0);
235
 
       if(barr_rcv_ptr[armci_me]==NULL || barr_snd_ptr[armci_me]==NULL)
236
 
         armci_die("problems in malloc barr_init",0);
237
 
       powof2nodes=1;
238
 
       LnB = floor(log(armci_nclus)/log(2))+1;
239
 
       if(pow(2,LnB-1)<armci_nclus){powof2nodes=0;}
240
 
       /*Lp2 is the largest pow-of-2 less than or equal to nclus(num of nodes)*/
241
 
       Lp2 = pow(2,LnB);
242
 
       _armci_barrier_init = 1;
243
 
     }
244
 
     /****************************************************/
245
 
#endif
246
 
     _armci_gop_init=1;
247
 
}
248
 
 
249
 
 
250
 
void armci_msg_gop_finalize() 
251
 
252
 
#if !defined(SGIALTIX) && defined(SYSV) || defined(MMAP) || defined(WIN32) 
253
 
    if(ARMCI_Uses_shm()){
254
 
        PARMCI_Free(ptr_arr[armci_me]); 
255
 
        free(ptr_arr); 
256
 
    }
257
 
#endif 
258
 
    _deallocate_mem_for_work(); 
259
 
260
 
 
261
 
 
262
 
void cpu_yield()
263
 
{
264
 
#if defined(SYSV) || defined(MMAP) || defined(WIN32)
265
 
#ifdef SOLARIS
266
 
               yield();
267
 
#elif defined(WIN32)
268
 
               Sleep(1);
269
 
#elif defined(_POSIX_PRIORITY_SCHEDULING)
270
 
               sched_yield();
271
 
#else
272
 
               usleep(1);
273
 
#endif
274
 
#endif
275
 
}
276
 
 
277
 
/*\ busy wait 
278
 
 *  n represents number of time delay units   
279
 
 *  notused is useful to fool compiler by passing address of sensitive variable 
280
 
\*/
281
 
#define DUMMY_INIT 1.0001
282
 
double _armci_dummy_work=DUMMY_INIT;
283
 
void armci_util_spin(int n, void *notused)
284
 
{
285
 
int i;
286
 
    for(i=0; i<n; i++)
287
 
        if(armci_msg_me()>-1)  _armci_dummy_work *=DUMMY_INIT;
288
 
    if(_armci_dummy_work>(double)armci_msg_nproc())_armci_dummy_work=DUMMY_INIT;
289
 
}
290
 
 
291
 
 
292
 
/***************************Barrier Code*************************************/
293
 
 
294
 
void armci_msg_barr_init(){
295
 
#if defined(SYSV) || defined(MMAP) || defined(WIN32)
296
 
    int size=sizeof(barrier_struct)*armci_clus_info[armci_clus_me].nslave;
297
 
    char *tmp;
298
 
    void **ptr_arr;
299
 
    barr_switch=0;
300
 
    /*First allocate space for flags*/
301
 
 
302
 
    ptr_arr = (void**)malloc(armci_nproc*sizeof(void*));
303
 
    if(armci_me==armci_master) size = size+128;
304
 
    else size=0;
305
 
    PARMCI_Malloc(ptr_arr, size);
306
 
    tmp = (char*)ptr_arr[armci_master];
307
 
    size=2*sizeof(int);
308
 
 
309
 
    if(!tmp)armci_die("allocate barr shm failed",0);
310
 
    _bar_buff=(barrier_struct *)tmp;
311
 
 
312
 
    SET_SHM_FLAG(&(BAR_BUF(armci_me-armci_master)->flag1),empty);
313
 
    SET_SHM_FLAG(&(BAR_BUF(armci_me-armci_master)->flag2),empty);
314
 
 
315
 
    /*allocate memory to send/rcv data*/
316
 
    barr_snd_ptr = (void **)malloc(sizeof(void *)*armci_nproc);
317
 
    barr_rcv_ptr = (void **)malloc(sizeof(void *)*armci_nproc);
318
 
 
319
 
    if(PARMCI_Malloc(barr_snd_ptr,size))armci_die("malloc barr_init failed",0);
320
 
    if(PARMCI_Malloc(barr_rcv_ptr,size))armci_die("malloc barr_init failed",0);
321
 
    if(barr_rcv_ptr[armci_me]==NULL || barr_snd_ptr[armci_me]==NULL)
322
 
       armci_die("problems in malloc barr_init",0);
323
 
 
324
 
    /*we have to figure if we have power of ,two nodes*/
325
 
    powof2nodes=1;
326
 
    LnB = (int)floor(log(armci_nclus)/log(2))+1;
327
 
    if(pow(2,LnB-1)<armci_nclus){powof2nodes=0;}
328
 
    /*Lp2 is the largest pow-of-2 less than or equal to nclus(num of nodes)*/
329
 
    Lp2 = (int)pow(2,LnB);
330
 
    _armci_barrier_shmem = 1;
331
 
#endif
332
 
    _armci_barrier_init = 1;
333
 
}
334
 
 
335
 
/*\
336
 
 *armci barrier: implemented as a recursive doubling based pairwise exchange
337
 
 *algorithm with SMP barrier inside a node and msg_snd/rcv between the nodes.
338
 
 *NOTE::code for power or two nodes and non power of two nodes can be combined.
339
 
\*/
340
 
#ifdef LAPI
341
 
static void _armci_msg_barrier(){
342
 
    int next_node,next,i;
343
 
    char *dstn,*srcp;
344
 
    int nslave = armci_clus_info[armci_clus_me].nslave;
345
 
    static int barr_count = 0;
346
 
    int last, next_nodel=0;
347
 
    void armci_util_wait_int(volatile int *,int,int);
348
 
    /*if(barr_count==0)armci_msg_barr_init();*/
349
 
    barr_count++;
350
 
    if(armci_me==armci_master){ /*only masters do the intenode barrier*/
351
 
       for(i=1;i<nslave;i++){   /*wait for all smp procs to enter the barrier*/
352
 
         armci_util_wait_int(&BAR_BUF(i)->flag1,FULL,100000);
353
 
         SET_SHM_FLAG(&(BAR_BUF(i)->flag1),empty);
354
 
       }
355
 
       if(armci_nclus>1){
356
 
       last =  ((int)pow(2,(LnB-1)))^armci_clus_me;
357
 
       if(last>=0 && last<armci_nclus)
358
 
         next_nodel = armci_clus_info[last].master;
359
 
       /*three step exchange if num of nodes is not pow of 2*/
360
 
       /*divide _nodes_ into two sets, first set "pow2" will have a power of 
361
 
        *two nodes, the second set "not-pow2" will have the remaining.
362
 
        *Each node in the not-pow2 set will have a pair node in the pow2 set.
363
 
        *Step-1:each node in pow2 set with a pair in not-pow2 set first recvs 
364
 
        *      :a message from its pair in not-pow2. 
365
 
        *step-2:All nodes in pow2 do a Rercusive Doubling based Pairwise exng.
366
 
        *step-3:Each node in pow2 with a pair in not-pow2 snds msg to its 
367
 
        *      :pair node.
368
 
        *if num of nodes a pow of 2, only step 2 executed
369
 
       */
370
 
       if(last>armci_clus_me){ /*the pow2 set of procs*/
371
 
         if(last<armci_nclus && !powof2nodes){ /*step 1*/
372
 
           dstn = (char *)barr_rcv_ptr[next_nodel];
373
 
           armci_msg_rcv(ARMCI_TAG, dstn,4,NULL,next_nodel);
374
 
           armci_util_wait_int((volatile int *)dstn,barr_count,100000);
375
 
         }
376
 
         for(i=0;i<LnB-1;i++){/*step 2*/
377
 
           next=((int)pow(2,i))^armci_clus_me;
378
 
           /*printf("\n%d:next=%d \n",armci_me,next);fflush(stdout);*/
379
 
           if(next>=0 && next<armci_nclus){
380
 
             next_node = armci_clus_info[next].master;
381
 
             /*printf("\n%d:node=%d -\n",armci_me,next_node);fflush(stdout);*/
382
 
             srcp = (char *)barr_snd_ptr[next_node];
383
 
             *(int *)srcp = barr_count;
384
 
             dstn = (char *)barr_rcv_ptr[next_node];
385
 
             if(next_node > armci_me){
386
 
               armci_msg_snd(ARMCI_TAG, srcp,4,next_node);
387
 
               armci_msg_rcv(ARMCI_TAG, dstn,4,NULL,next_node);
388
 
             }
389
 
             else{
390
 
               /*would we gain anything by doing a snd,rcv instead of rcv,snd*/
391
 
               armci_msg_rcv(ARMCI_TAG, dstn,4,NULL,next_node);
392
 
               armci_msg_snd(ARMCI_TAG, srcp,4,next_node);
393
 
             }
394
 
             armci_util_wait_int((volatile int *)dstn,barr_count,100000);
395
 
           }
396
 
         }
397
 
         if(last<armci_nclus && !powof2nodes){ /*step 3*/
398
 
           srcp = (char *)barr_snd_ptr[next_nodel];
399
 
           *(int *)srcp = barr_count;
400
 
           armci_msg_snd(ARMCI_TAG, srcp,4,next_nodel);
401
 
         }
402
 
       }
403
 
       else {
404
 
         if(!powof2nodes){
405
 
           srcp = (char *)barr_snd_ptr[next_nodel];
406
 
           *(int *)srcp = barr_count;
407
 
           dstn = (char *)barr_rcv_ptr[next_nodel];
408
 
           armci_msg_snd(ARMCI_TAG, srcp,4,next_nodel);
409
 
           armci_msg_rcv(ARMCI_TAG, dstn,4,NULL,next_nodel);
410
 
           armci_util_wait_int((volatile int *)dstn,barr_count,100000);
411
 
         }
412
 
       }
413
 
       } /* paranthesis for if armci_nclus>1*/
414
 
       for(i=1;i<nslave;i++) /*tell smp procs that internode barrier complete*/
415
 
         SET_SHM_FLAG(&(BAR_BUF(i)->flag2),full);
416
 
    }
417
 
    else {                   /*if not master, partake in the smp barrier,only*/
418
 
       i=armci_me-armci_master;
419
 
       SET_SHM_FLAG(&(BAR_BUF(i)->flag1),full);
420
 
       armci_util_wait_int(&BAR_BUF(i)->flag2,FULL,100000);
421
 
       SET_SHM_FLAG(&(BAR_BUF(i)->flag2),empty);
422
 
    }
423
 
}
424
 
       
425
 
#endif /*barrier enabled only for lapi*/
426
 
void parmci_msg_barrier()
427
 
{
428
 
#ifdef BGML
429
 
  bgml_barrier (3); /* this is always faster than MPI_Barrier() */
430
 
#elif defined(MPI)
431
 
     MPI_Barrier(ARMCI_COMM_WORLD);
432
 
#  elif defined(PVM)
433
 
     pvm_barrier(mp_group_name, armci_nproc);
434
 
#  elif defined(LAPI)
435
 
#if !defined(NEED_MEM_SYNC)
436
 
     if(_armci_barrier_init)
437
 
       _armci_msg_barrier();
438
 
     else
439
 
#endif
440
 
     {
441
 
       tcg_synch(ARMCI_TAG);
442
 
     }
443
 
#  else
444
 
     {
445
 
        tcg_synch(ARMCI_TAG);
446
 
     }
447
 
#  endif
448
 
}
449
 
/***********************End Barrier Code*************************************/
450
 
 
451
 
 
452
 
void armci_msg_init(int *argc, char ***argv)
453
 
{
454
 
#if defined(TCGMSG)
455
 
    if (!tcg_ready()) {
456
 
        tcg_pbegin(*argc,*argv);
457
 
    }
458
 
#elif defined(BGML)
459
 
    /* empty */
460
 
#elif defined(MPI)
461
 
    int flag=0;
462
 
    MPI_Initialized(&flag);
463
 
    if (!flag) {
464
 
#   if defined(DCMF) || defined(MPI_MT)
465
 
        int provided;
466
 
        MPI_Init_thread(argc, argv, MPI_THREAD_MULTIPLE, &provided);
467
 
#   else
468
 
        MPI_Init(argc, argv);
469
 
#   endif
470
 
    }
471
 
    if (!PARMCI_Initialized()) {
472
 
        MPI_Comm_dup(MPI_COMM_WORLD, &ARMCI_COMM_WORLD);
473
 
    }
474
 
#endif
475
 
}
476
 
 
477
 
 
478
 
int armci_msg_me()
479
 
{
480
 
#ifdef BGML
481
 
    return BGML_Messager_rank();
482
 
#elif defined(DCMF)
483
 
    return DCMF_Messager_rank();
484
 
#elif defined(MPI)
485
 
    static int counter = 0;
486
 
    if (counter == 0) {
487
 
        int me;
488
 
        MPI_Comm_rank(ARMCI_COMM_WORLD, &me);
489
 
        armci_me = me;   
490
 
        counter = 1;
491
 
    }
492
 
    return armci_me;
493
 
 
494
 
#elif defined(PVM)
495
 
    return(pvm_getinst(mp_group_name,pvm_mytid()));
496
 
#else
497
 
    return (int)tcg_nodeid();
498
 
#endif
499
 
}
500
 
 
501
 
 
502
 
int armci_msg_nproc()
503
 
{
504
 
#ifdef BGML
505
 
    return BGML_Messager_size();
506
 
#elif defined(DCMF)
507
 
    return DCMF_Messager_size();
508
 
#elif defined(MPI)
509
 
    static int counter = 0;
510
 
    if (counter == 0) {
511
 
        int nproc;
512
 
        MPI_Comm_size(ARMCI_COMM_WORLD, &nproc);
513
 
        armci_nproc = nproc;
514
 
        counter = 1;
515
 
    }
516
 
    return armci_nproc;
517
 
#elif defined(PVM)
518
 
    return(pvm_gsize(mp_group_name));
519
 
#else
520
 
    return (int)tcg_nnodes();
521
 
#endif
522
 
}
523
 
 
524
 
#ifdef CRAY_YMP
525
 
#define BROKEN_MPI_ABORT
526
 
#endif
527
 
 
528
 
#ifndef PVM
529
 
double armci_timer()
530
 
{
531
 
#ifdef BGML
532
 
    return BGML_Timer();
533
 
#elif defined(DCMF)
534
 
    return DCMF_Timer();
535
 
#elif defined(MPI)
536
 
 
537
 
    return MPI_Wtime();
538
 
#else
539
 
    return tcg_time();
540
 
#endif
541
 
}
542
 
#endif
543
 
 
544
 
 
545
 
void armci_msg_abort(int code)
546
 
{
547
 
#ifdef BGML
548
 
    fprintf(stderr,"ARMCI aborting [%d]\n", code);
549
 
#elif defined(DCMF)
550
 
    fprintf(stderr,"ARMCI aborting [%d]\n", code);
551
 
#elif defined(MPI)
552
 
#    ifndef BROKEN_MPI_ABORT
553
 
    MPI_Abort(ARMCI_COMM_WORLD,code);
554
 
#    endif
555
 
#elif defined(PVM)
556
 
    char error_msg[25];
557
 
    sprintf(error_msg, "ARMCI aborting [%d]", code);
558
 
    pvm_halt();
559
 
#else
560
 
    tcg_error("ARMCI aborting",(long)code);
561
 
#endif
562
 
    fprintf(stderr,"%d:aborting\n",armci_me);
563
 
    /* trap for broken abort in message passing libs */
564
 
    _exit(1);
565
 
}
566
 
 
567
 
void armci_msg_finalize()
568
 
{
569
 
#if defined(TCGMSG)
570
 
    tcg_pend();
571
 
#elif defined(MPI)
572
 
    MPI_Finalize();
573
 
#endif
574
 
}
575
 
 
576
 
void armci_msg_bintree(int scope, int* Root, int *Up, int *Left, int *Right)
577
 
{
578
 
int root, up, left, right, index, nproc;
579
 
    if(scope == SCOPE_NODE){
580
 
       root  = armci_clus_info[armci_clus_me].master;
581
 
       nproc = armci_clus_info[armci_clus_me].nslave;
582
 
       index = armci_me - root;
583
 
       up    = (index-1)/2 + root; if( up < root) up = -1;
584
 
       left  = 2*index + 1 + root; if(left >= root+nproc) left = -1;
585
 
       right = 2*index + 2 + root; if(right >= root+nproc)right = -1;
586
 
    }else if(scope ==SCOPE_MASTERS){
587
 
       root  = armci_clus_info[0].master;
588
 
       nproc = armci_nclus;
589
 
       if(armci_me != armci_master){up = -1; left = -1; right = -1; }
590
 
       else{
591
 
               index = armci_clus_me - root;
592
 
               up    = (index-1)/2 + root;
593
 
               up = ( up < root)? -1: armci_clus_info[up].master;
594
 
               left  = 2*index + 1 + root;
595
 
               left = ( left >= root+nproc)? -1: armci_clus_info[left].master;
596
 
               right = 2*index + 2 + root;
597
 
               right =( right >= root+nproc)? -1: armci_clus_info[right].master;
598
 
       }
599
 
    }else{
600
 
       root  = 0;
601
 
       nproc = armci_nproc;
602
 
       index = armci_me - root;
603
 
       up    = (index-1)/2 + root; if( up < root) up = -1;
604
 
       left  = 2*index + 1 + root; if(left >= root+nproc) left = -1;
605
 
       right = 2*index + 2 + root; if(right >= root+nproc)right = -1;
606
 
    }
607
 
 
608
 
    *Up = up;
609
 
    *Left = left;
610
 
    *Right = right;
611
 
    *Root = root;
612
 
}
613
 
 
614
 
/*\ root broadcasts to everyone else
615
 
\*/
616
 
void armci_msg_bcast_scope(int scope, void *buf, int len, int root)
617
 
{
618
 
    int up, left, right, Root;
619
 
 
620
 
    if(!buf)armci_die("armci_msg_bcast: NULL pointer", len);
621
 
#ifdef BGML
622
 
        BGTr_Bcast(root, buf, len, 3);
623
 
#else
624
 
    armci_msg_bintree(scope, &Root, &up, &left, &right);
625
 
 
626
 
    if(root !=Root){
627
 
        if(armci_me == root) armci_msg_snd(ARMCI_TAG, buf,len, Root);
628
 
        if(armci_me ==Root) armci_msg_rcv(ARMCI_TAG, buf, len, NULL, root);
629
 
    }
630
 
    
631
 
    /* printf("%d: scope=%d left=%d right=%d up=%d\n",armci_me, scope, 
632
 
    left, right, up);*/
633
 
 
634
 
    if(armci_me != Root && up!=-1) armci_msg_rcv(ARMCI_TAG, buf, len, NULL, up);
635
 
    if (left > -1)  armci_msg_snd(ARMCI_TAG, buf, len, left);
636
 
    if (right > -1) armci_msg_snd(ARMCI_TAG, buf, len, right);
637
 
#endif
638
 
}
639
 
 
640
 
 
641
 
 
642
 
 
643
 
/*\ shared memory based broadcast for a single SMP node
644
 
\*/
645
 
void armci_smp_bcast(void *x, int n , int root)
646
 
{
647
 
int ndo, len,i, bufsize = BUF_SIZE*sizeof(double);
648
 
static int bufid=1;
649
 
 
650
 
  if(armci_clus_info[armci_clus_me].nslave<2) return; /* nothing to do */
651
 
 
652
 
  if(!x)armci_die("armci_msg_bcast: NULL pointer", n);
653
 
  
654
 
  /* enable or balance pipeline for messages comparable to bufsize */
655
 
  if((n>bufsize/2) && (n <(2*bufsize-64))){
656
 
      bufsize = n/2; bufsize>>=3; bufsize<<=3; 
657
 
  }
658
 
 
659
 
  while ((ndo = (n<=bufsize) ? n : bufsize)) {
660
 
    len = ndo;
661
 
          
662
 
    if(armci_me==root){
663
 
 
664
 
       /* wait for the flag protecting the buffer to clear */
665
 
       armci_util_wait_int(&(GOP_BUF(armci_clus_last+bufid)->a.flag),EMPTY,100);
666
 
       SET_SHM_FLAG(&(GOP_BUF(armci_clus_last+bufid)->a.flag),full);
667
 
#if 0     
668
 
       for(i=armci_clus_first; i <= armci_clus_last; i++)
669
 
           if(i!=root)armci_util_wait_int(&GOP_BUF(i)->b.flag, EMPTY, 100);
670
 
       armci_copy(x,GOP_BUF(armci_clus_last+bufid+1)->array,len);
671
 
       for(i=armci_clus_first; i <= armci_clus_last; i++)
672
 
           if(i!=root) GOP_BUF(i)->b.flag=FULL;
673
 
#else   
674
 
       armci_copy(x,GOP_BUF(armci_clus_last+bufid)->array,len);
675
 
       for(i=armci_clus_first; i <= armci_clus_last; i++)
676
 
           if(i!=root){ 
677
 
                  armci_util_wait_int(&GOP_BUF(i)->b.flag, EMPTY, 100);
678
 
                  SET_SHM_FLAG(&(GOP_BUF(i)->b.flag),full);
679
 
           } 
680
 
#endif            
681
 
    }else{     
682
 
           armci_util_wait_int(&GOP_BUF(armci_me)->b.flag, FULL, 100);
683
 
           armci_copy(GOP_BUF(armci_clus_last+bufid)->array,x,len);
684
 
           SET_SHM_FLAG(&(GOP_BUF(armci_me)->b.flag),empty);
685
 
    }
686
 
 
687
 
    n -=ndo;
688
 
    x = len + (char*)x;
689
 
       
690
 
    bufid = (bufid)%2 +1;
691
 
 
692
 
    /* since root waited for everybody to check in the previous buffer is free*/
693
 
    if(armci_me==root){
694
 
          SET_SHM_FLAG(&(GOP_BUF(armci_clus_last+bufid)->a.flag),empty);
695
 
    }
696
 
  }    
697
 
}        
698
 
 
699
 
 
700
 
 
701
 
/*\ shared memory based broadcast for a single SMP node out of shmem buffer
702
 
\*/
703
 
void armci_smp_buf_bcast(void *x, int n, int root, void *shmbuf )
704
 
{
705
 
int i, nslave = armci_clus_info[armci_clus_me].nslave;
706
 
 
707
 
    if(nslave<2){
708
 
        armci_copy(shmbuf,x,n);
709
 
        return; /* nothing to do */
710
 
    }
711
 
    if(!x)armci_die("armci_msg_bcast: NULL pointer", n);
712
 
    if(!shmbuf)armci_die("armci_msg_bcast: NULL pointer", n);
713
 
 
714
 
    if(armci_me==root){
715
 
          /* notify others that the data in buffer is ready */
716
 
          for(i=armci_clus_first; i <= armci_clus_last; i++)
717
 
                if(i!=root){
718
 
                  armci_util_wait_int(&GOP_BUF(i)->b.flag, EMPTY, 100);
719
 
                  GOP_BUF(i)->b.flag=FULL;
720
 
                }
721
 
          /* root also needs to copy */
722
 
          armci_copy(shmbuf,x,n);
723
 
          /* wait until everybody is finished -- can reclaim buffer */
724
 
          for(i=armci_clus_first; i <= armci_clus_last; i++)
725
 
              if(i!=root)armci_util_wait_int(&GOP_BUF(i)->b.flag, EMPTY,100000);
726
 
          
727
 
    }else{
728
 
           /* spin until data in buffer is ready */
729
 
           armci_util_wait_int(&GOP_BUF(armci_me)->b.flag , FULL, 100000);
730
 
           armci_copy(shmbuf,x,n);       /* copy data */
731
 
           GOP_BUF(armci_me)->b.flag  = EMPTY; /* indicate we are done */
732
 
    }
733
 
}
734
 
 
735
 
void _armci_msg_binomial_bcast(void *buf, int len, int root){
736
 
    int Root = armci_master;
737
 
    int nslave = armci_clus_info[armci_clus_me].nslave;
738
 
    int i,next_node,next;
739
 
/*    int my_rank,root_rank,next_rank; */
740
 
    /* inter-node operation between masters */
741
 
    if(root !=armci_clus_info[0].master){
742
 
       Root = armci_clus_info[0].master;
743
 
       if(armci_me == root) armci_msg_snd(ARMCI_TAG, buf,len, Root);
744
 
       if(armci_me ==Root) armci_msg_rcv(ARMCI_TAG, buf, len, NULL, root);
745
 
       root = Root;
746
 
       Root = armci_master;
747
 
    }
748
 
    if(armci_nclus>1 &&armci_me==armci_master){/*the internode bcast, first*/
749
 
       /*first do the recv*/
750
 
       int rcv_proc=armci_clus_me,flag=1,diff=1;
751
 
       if(armci_me!=root){
752
 
         while(!(rcv_proc & flag)){
753
 
           diff=diff<<1;
754
 
           flag=flag<<1;
755
 
         }
756
 
         rcv_proc = armci_clus_info[armci_clus_me-diff].master;
757
 
         armci_msg_rcv(ARMCI_TAG, buf,len,NULL,rcv_proc);
758
 
         /*printf("\n%d: recv from %d \n",armci_me,rcv_proc);fflush(stdout);*/
759
 
       }    
760
 
       else
761
 
         diff = Lp2;
762
 
 
763
 
       /*printf("\n%d: %d diff>>1 = %d\n",armci_me,Lp2,diff>>1);*/
764
 
       for(i=diff>>1;i>=1;i=i>>1){
765
 
         next=i^armci_clus_me;
766
 
         if(next>=0 && next<armci_nclus){
767
 
           next_node = armci_clus_info[next].master;
768
 
           armci_msg_snd(ARMCI_TAG, buf,len,next_node);
769
 
           /*printf("\n%d: send to %d \n",armci_me,next_node);fflush(stdout);*/
770
 
         }
771
 
       }
772
 
    }
773
 
    else  Root = root;
774
 
    if(_armci_gop_shmem && nslave<33)
775
 
       armci_smp_bcast(buf, len, Root);
776
 
    else
777
 
       armci_msg_bcast_scope(SCOPE_NODE, buf, len, Root);
778
 
}
779
 
 
780
 
 
781
 
 
782
 
#ifndef armci_msg_bcast
783
 
/*\ SMP-aware global broadcast routine
784
 
\*/
785
 
void armci_msg_bcast(void *buf, int len, int root)
786
 
{
787
 
int Root = armci_master;
788
 
int nslave = armci_clus_info[armci_clus_me].nslave;
789
 
 
790
 
#if defined(MPI_SPAWN) || defined(MPI_MT)
791
 
    armci_msg_bcast_scope(SCOPE_ALL, (buf), (len), (root));
792
 
    return;
793
 
#endif
794
 
#ifdef LAPI
795
 
    if(_armci_gop_init){_armci_msg_binomial_bcast(buf,len,root);return;}
796
 
#endif
797
 
    /* inter-node operation between masters */
798
 
    if(armci_nclus>1)armci_msg_bcast_scope(SCOPE_MASTERS, buf, len, root);
799
 
    else  Root = root;
800
 
 
801
 
    /* intra-node operation */
802
 
#if 1
803
 
    if(_armci_gop_shmem && nslave<33)
804
 
       armci_smp_bcast(buf, len, Root);
805
 
    else
806
 
#endif
807
 
    armci_msg_bcast_scope(SCOPE_NODE, buf, len, Root);
808
 
}
809
 
#endif
810
 
 
811
 
 
812
 
 
813
 
void armci_msg_brdcst(void* buffer, int len, int root)
814
 
{
815
 
   if(!buffer)armci_die("armci_msg_brdcast: NULL pointer", len);
816
 
 
817
 
#ifdef BGML
818
 
   BGTr_Bcast(root, buffer, len, PCLASS);
819
 
# elif defined(MPI)
820
 
      MPI_Bcast(buffer, len, MPI_CHAR, root, ARMCI_COMM_WORLD);
821
 
#  elif defined(PVM)
822
 
      armci_msg_bcast(buffer, len, root);
823
 
#  else
824
 
   {
825
 
      long ttag=ARMCI_TAG, llen=len, rroot=root;
826
 
      tcg_brdcst(ttag, buffer, llen, rroot);
827
 
   }
828
 
#  endif
829
 
}
830
 
 
831
 
 
832
 
void armci_msg_snd(int tag, void* buffer, int len, int to)
833
 
{
834
 
#  ifdef MPI
835
 
      MPI_Send(buffer, len, MPI_CHAR, to, tag, ARMCI_COMM_WORLD);
836
 
#  elif defined(PVM)
837
 
      pvm_psend(pvm_gettid(mp_group_name, to), tag, buffer, len, PVM_BYTE);
838
 
# elif defined(BGML)
839
 
      /* We don't actually used armci_msg_snd in ARMCI. we use optimized 
840
 
       * collectives where
841
 
       * armci_msg_snd is used. If you build Global Arrays, the MPI flag is 
842
 
       * set, so that
843
 
       * will work fine 
844
 
       */
845
 
      armci_die("bgl shouldn't use armci_msg_snd", armci_me);
846
 
#  else
847
 
      long ttag=tag, llen=len, tto=to, block=1;
848
 
      tcg_snd(ttag, buffer, llen, tto, block);
849
 
#  endif
850
 
}
851
 
 
852
 
 
853
 
/*\ receive message of specified tag from proc and get its len if msglen!=NULL 
854
 
\*/
855
 
void armci_msg_rcv(int tag, void* buffer, int buflen, int *msglen, int from)
856
 
{
857
 
#  ifdef MPI
858
 
      MPI_Status status;
859
 
      MPI_Recv(buffer, buflen, MPI_CHAR, from, tag, ARMCI_COMM_WORLD, &status);
860
 
      if(msglen) MPI_Get_count(&status, MPI_CHAR, msglen);
861
 
#  elif defined(PVM)
862
 
      int src, rtag,mlen;
863
 
      pvm_precv(pvm_gettid(mp_group_name, from), tag, buffer, buflen, PVM_BYTE,
864
 
                &src, &rtag, &mlen);
865
 
      if(msglen)*msglen=mlen;
866
 
#elif defined(BGML)
867
 
            armci_die("bgl shouldn't use armci_msg_rcv", armci_me);
868
 
#  else
869
 
      long ttag=tag, llen=buflen, mlen, ffrom=from, sender, block=1;
870
 
      tcg_rcv(ttag, buffer, llen, &mlen, ffrom, &sender, block);
871
 
      if(msglen)*msglen = (int)mlen;
872
 
#  endif
873
 
}
874
 
 
875
 
 
876
 
int armci_msg_rcvany(int tag, void* buffer, int buflen, int *msglen)
877
 
{
878
 
#if defined(MPI)
879
 
      int ierr;
880
 
      MPI_Status status;
881
 
 
882
 
      ierr = MPI_Recv(buffer, buflen, MPI_CHAR, MPI_ANY_SOURCE, tag,
883
 
             ARMCI_COMM_WORLD, &status);
884
 
      if(ierr != MPI_SUCCESS) armci_die("armci_msg_rcvany: Recv failed ", tag);
885
 
 
886
 
      if(msglen)if(MPI_SUCCESS!=MPI_Get_count(&status, MPI_CHAR, msglen))
887
 
                       armci_die("armci_msg_rcvany: count failed ", tag);
888
 
      return (int)status.MPI_SOURCE;
889
 
#  elif defined(PVM)
890
 
      int src, rtag,mlen;
891
 
      pvm_precv(-1, tag, buffer, buflen, PVM_BYTE, &src, &rtag, &mlen);
892
 
      if(msglen)*msglen=mlen;
893
 
      return(pvm_getinst(mp_group_name,src));
894
 
# elif defined (BGML)
895
 
      armci_die("bgl shouldn't use armci_msg_rcvany", armci_me);
896
 
#  else
897
 
      long ttag=tag, llen=buflen, mlen, ffrom=-1, sender, block=1;
898
 
      tcg_rcv(ttag, buffer, llen, &mlen, ffrom, &sender, block);
899
 
      if(msglen)*msglen = (int)mlen;
900
 
      return (int)sender;
901
 
#  endif
902
 
}
903
 
 
904
 
 
905
 
/*\ cluster master broadcasts to everyone else in the same cluster
906
 
\*/
907
 
void armci_msg_clus_brdcst(void *buf, int len)
908
 
{
909
 
int root, up, left, right;
910
 
int tag=ARMCI_TAG, lenmes;
911
 
 
912
 
    armci_msg_bintree(SCOPE_NODE, &root, &up, &left, &right);
913
 
    if(armci_me != root) armci_msg_rcv(tag, buf, len, &lenmes, up);
914
 
    if (left > -1)  armci_msg_snd(tag, buf, len, left);
915
 
    if (right > -1) armci_msg_snd(tag, buf, len, right);
916
 
}
917
 
 
918
 
 
919
 
/*\ reduce operation for long 
920
 
\*/
921
 
static void ldoop(int n, char *op, long *x, long* work)
922
 
{
923
 
  if (strncmp(op,"+",1) == 0)
924
 
    while(n--)
925
 
      *x++ += *work++;
926
 
  else if (strncmp(op,"*",1) == 0)
927
 
    while(n--)
928
 
      *x++ *= *work++;
929
 
  else if (strncmp(op,"max",3) == 0)
930
 
    while(n--) {
931
 
      *x = ARMCI_MAX(*x, *work);
932
 
      x++; work++;
933
 
    }
934
 
  else if (strncmp(op,"min",3) == 0)
935
 
    while(n--) {
936
 
      *x = ARMCI_MIN(*x, *work);
937
 
      x++; work++;
938
 
    }
939
 
  else if (strncmp(op,"absmax",6) == 0)
940
 
    while(n--) {
941
 
      register long x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
942
 
      *x = ARMCI_MAX(x1, x2);
943
 
      x++; work++;
944
 
    }
945
 
  else if (strncmp(op,"absmin",6) == 0)
946
 
    while(n--) {
947
 
      register long x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
948
 
      *x = ARMCI_MIN(x1, x2);
949
 
      x++; work++;
950
 
    }
951
 
  else if (strncmp(op,"or",2) == 0)
952
 
    while(n--) {
953
 
      *x |= *work;
954
 
      x++; work++;
955
 
    }
956
 
  else
957
 
    armci_die("ldoop: unknown operation requested", n);
958
 
}
959
 
 
960
 
/*\ reduce operation for long x= op(work,work2)
961
 
\*/
962
 
static void ldoop2(int n, char *op, long *x, long* work, long* work2)
963
 
{
964
 
  if (strncmp(op,"+",1) == 0)
965
 
    while(n--)
966
 
      *x++ = *work++ + *work2++;
967
 
  else if (strncmp(op,"*",1) == 0)
968
 
    while(n--)
969
 
      *x++ = *work++ *  *work2++;
970
 
  else if (strncmp(op,"max",3) == 0)
971
 
    while(n--) {
972
 
      *x = ARMCI_MAX(*work2, *work);
973
 
      x++; work++; work2++;
974
 
    }
975
 
  else if (strncmp(op,"min",3) == 0)
976
 
    while(n--) {
977
 
      *x = ARMCI_MIN(*work2, *work);
978
 
      x++; work++; work2++;
979
 
    }
980
 
  else if (strncmp(op,"absmax",6) == 0)
981
 
    while(n--) {
982
 
      register long x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
983
 
      *x = ARMCI_MAX(x1, x2);
984
 
      x++; work++; work2++;
985
 
    }
986
 
  else if (strncmp(op,"absmin",6) == 0)
987
 
    while(n--) {
988
 
      register long x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
989
 
      *x = ARMCI_MIN(x1, x2);
990
 
      x++; work++; work2++;
991
 
    }
992
 
  else if (strncmp(op,"or",2) == 0)
993
 
    while(n--) {
994
 
      *x = *work | *work2;
995
 
      x++; work++; work2++;
996
 
    }
997
 
  else
998
 
    armci_die("ldoop2: unknown operation requested", n);
999
 
}
1000
 
 
1001
 
/*\ reduce operation for long long
1002
 
\*/
1003
 
static void lldoop(int n, char *op, long long *x, long long* work)
1004
 
{
1005
 
  if (strncmp(op,"+",1) == 0)
1006
 
    while(n--)
1007
 
      *x++ += *work++;
1008
 
  else if (strncmp(op,"*",1) == 0)
1009
 
    while(n--)
1010
 
      *x++ *= *work++;
1011
 
  else if (strncmp(op,"max",3) == 0)
1012
 
    while(n--) {
1013
 
      *x = ARMCI_MAX(*x, *work);
1014
 
      x++; work++;
1015
 
    }
1016
 
  else if (strncmp(op,"min",3) == 0)
1017
 
    while(n--) {
1018
 
      *x = ARMCI_MIN(*x, *work);
1019
 
      x++; work++;
1020
 
    }
1021
 
  else if (strncmp(op,"absmax",6) == 0)
1022
 
    while(n--) {
1023
 
      register long long x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1024
 
      *x = ARMCI_MAX(x1, x2);
1025
 
      x++; work++;
1026
 
    }
1027
 
  else if (strncmp(op,"absmin",6) == 0)
1028
 
    while(n--) {
1029
 
      register long long x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1030
 
      *x = ARMCI_MIN(x1, x2);
1031
 
      x++; work++;
1032
 
    }
1033
 
  else if (strncmp(op,"or",2) == 0)
1034
 
    while(n--) {
1035
 
      *x |= *work;
1036
 
      x++; work++;
1037
 
    }
1038
 
  else
1039
 
    armci_die("lldoop: unknown operation requested", n);
1040
 
}
1041
 
 
1042
 
/*\ reduce operation for long long x= op(work,work2)
1043
 
\*/
1044
 
static void lldoop2(int n, char *op, long long *x, long long* work,
1045
 
                    long long* work2)
1046
 
{
1047
 
  if (strncmp(op,"+",1) == 0)
1048
 
    while(n--)
1049
 
      *x++ = *work++ + *work2++;
1050
 
  else if (strncmp(op,"*",1) == 0)
1051
 
    while(n--)
1052
 
      *x++ = *work++ *  *work2++;
1053
 
  else if (strncmp(op,"max",3) == 0)
1054
 
    while(n--) {
1055
 
      *x = ARMCI_MAX(*work2, *work);
1056
 
      x++; work++; work2++;
1057
 
    }
1058
 
  else if (strncmp(op,"min",3) == 0)
1059
 
    while(n--) {
1060
 
      *x = ARMCI_MIN(*work2, *work);
1061
 
      x++; work++; work2++;
1062
 
    }
1063
 
  else if (strncmp(op,"absmax",6) == 0)
1064
 
    while(n--) {
1065
 
      register long long x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1066
 
      *x = ARMCI_MAX(x1, x2);
1067
 
      x++; work++; work2++;
1068
 
    }
1069
 
  else if (strncmp(op,"absmin",6) == 0)
1070
 
    while(n--) {
1071
 
      register long long x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1072
 
      *x = ARMCI_MIN(x1, x2);
1073
 
      x++; work++; work2++;
1074
 
    }
1075
 
  else if (strncmp(op,"or",2) == 0)
1076
 
    while(n--) {
1077
 
      *x = *work | *work2;
1078
 
      x++; work++; work2++;
1079
 
    }
1080
 
  else
1081
 
    armci_die("ldoop2: unknown operation requested", n);
1082
 
}
1083
 
 
1084
 
/*\ reduce operation for int 
1085
 
\*/
1086
 
static void idoop(int n, char *op, int *x, int* work)
1087
 
{
1088
 
  if (strncmp(op,"+",1) == 0)
1089
 
    while(n--)
1090
 
      *x++ += *work++;
1091
 
  else if (strncmp(op,"*",1) == 0)
1092
 
    while(n--)
1093
 
      *x++ *= *work++;
1094
 
  else if (strncmp(op,"max",3) == 0)
1095
 
    while(n--) {
1096
 
      *x = ARMCI_MAX(*x, *work);
1097
 
      x++; work++;
1098
 
    }
1099
 
  else if (strncmp(op,"min",3) == 0)
1100
 
    while(n--) {
1101
 
      *x = ARMCI_MIN(*x, *work);
1102
 
      x++; work++;
1103
 
    }
1104
 
  else if (strncmp(op,"absmax",6) == 0)
1105
 
    while(n--) {
1106
 
      register int x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1107
 
      *x = ARMCI_MAX(x1, x2);
1108
 
      x++; work++;
1109
 
    }
1110
 
  else if (strncmp(op,"absmin",6) == 0)
1111
 
    while(n--) {
1112
 
      register int x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1113
 
      *x = ARMCI_MIN(x1, x2);
1114
 
      x++; work++;
1115
 
    }
1116
 
  else if (strncmp(op,"or",2) == 0)
1117
 
    while(n--) {
1118
 
      *x |= *work;
1119
 
      x++; work++;
1120
 
    }
1121
 
  else
1122
 
    armci_die("idoop: unknown operation requested", n);
1123
 
}
1124
 
 
1125
 
/*\ reduce operation for int x= op(work,work2)
1126
 
\*/
1127
 
static void idoop2(int n, char *op, int *x, int* work, int* work2)
1128
 
{
1129
 
  if (strncmp(op,"+",1) == 0)
1130
 
    while(n--)
1131
 
      *x++ = *work++ + *work2++;
1132
 
  else if (strncmp(op,"*",1) == 0)
1133
 
    while(n--)
1134
 
      *x++ = *work++ *  *work2++;
1135
 
  else if (strncmp(op,"max",3) == 0)
1136
 
    while(n--) {
1137
 
      *x = ARMCI_MAX(*work2, *work);
1138
 
      x++; work++; work2++;
1139
 
    }
1140
 
  else if (strncmp(op,"min",3) == 0)
1141
 
    while(n--) {
1142
 
      *x = ARMCI_MIN(*work2, *work);
1143
 
      x++; work++; work2++;
1144
 
    }
1145
 
  else if (strncmp(op,"absmax",6) == 0)
1146
 
    while(n--) {
1147
 
      register int x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1148
 
      *x = ARMCI_MAX(x1, x2);
1149
 
      x++; work++; work2++;
1150
 
    }
1151
 
  else if (strncmp(op,"absmin",6) == 0)
1152
 
    while(n--) {
1153
 
      register int x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1154
 
      *x = ARMCI_MIN(x1, x2);
1155
 
      x++; work++; work2++;
1156
 
    }
1157
 
  else if (strncmp(op,"or",2) == 0)
1158
 
    while(n--) {
1159
 
      *x = *work | *work2;
1160
 
      x++; work++; work2++;
1161
 
    }
1162
 
  else
1163
 
    armci_die("idoop2: unknown operation requested", n);
1164
 
}
1165
 
 
1166
 
/*\ reduce operation for double 
1167
 
\*/
1168
 
static void ddoop(int n, char* op, double* x, double* work)
1169
 
{
1170
 
  if (strncmp(op,"+",1) == 0){
1171
 
    if(n>63) FORT_DADD(&n,x,work);
1172
 
    else while(n--) *x++ += *work++;
1173
 
  }else if (strncmp(op,"*",1) == 0){
1174
 
    if(n>63) FORT_DMULT(&n,x,work);
1175
 
    else while(n--) *x++ *= *work++;
1176
 
  }else if (strncmp(op,"max",3) == 0)
1177
 
    while(n--) {
1178
 
      *x = ARMCI_MAX(*x, *work);
1179
 
      x++; work++;
1180
 
    }
1181
 
  else if (strncmp(op,"min",3) == 0)
1182
 
    while(n--) {
1183
 
      *x = ARMCI_MIN(*x, *work);
1184
 
      x++; work++;
1185
 
    }
1186
 
  else if (strncmp(op,"absmax",6) == 0)
1187
 
    while(n--) {
1188
 
      register double x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1189
 
      *x = ARMCI_MAX(x1, x2);
1190
 
      x++; work++;
1191
 
    }
1192
 
  else if (strncmp(op,"absmin",6) == 0)
1193
 
    while(n--) {
1194
 
      register double x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1195
 
      *x = ARMCI_MIN(x1, x2);
1196
 
      x++; work++;
1197
 
    }
1198
 
  else
1199
 
    armci_die("ddoop: unknown operation requested", n);
1200
 
}
1201
 
 
1202
 
/*\ reduce operation for double x= op(work,work2)
1203
 
\*/
1204
 
static void ddoop2(int n, char *op, double *x, double* work, double* work2)
1205
 
{
1206
 
  if (strncmp(op,"+",1) == 0){
1207
 
    if(n>63) FORT_DADD2(&n,x,work,work2);
1208
 
    else while(n--) *x++ = *work++ + *work2++;
1209
 
  }else if (strncmp(op,"*",1) == 0){
1210
 
    if(n>63) FORT_DMULT2(&n,x,work,work2);
1211
 
    while(n--) *x++ = *work++ *  *work2++;
1212
 
  }else if (strncmp(op,"max",3) == 0)
1213
 
    while(n--) {
1214
 
      *x = ARMCI_MAX(*work2, *work);
1215
 
      x++; work++; work2++;
1216
 
    }
1217
 
  else if (strncmp(op,"min",3) == 0)
1218
 
    while(n--) {
1219
 
      *x = ARMCI_MIN(*work2, *work);
1220
 
      x++; work++; work2++;
1221
 
    }
1222
 
  else if (strncmp(op,"absmax",6) == 0)
1223
 
    while(n--) {
1224
 
      register double x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1225
 
      *x = ARMCI_MAX(x1, x2);
1226
 
      x++; work++; work2++;
1227
 
    }
1228
 
  else if (strncmp(op,"absmin",6) == 0)
1229
 
    while(n--) {
1230
 
      register double x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1231
 
      *x = ARMCI_MIN(x1, x2);
1232
 
      x++; work++; work2++;
1233
 
    }
1234
 
  else
1235
 
    armci_die("ddoop2: unknown operation requested", n);
1236
 
}
1237
 
 
1238
 
 
1239
 
/*\ reduce operation for float 
1240
 
\*/
1241
 
static void fdoop(int n, char* op, float* x, float* work)
1242
 
{
1243
 
  if (strncmp(op,"+",1) == 0)
1244
 
    while(n--)
1245
 
      *x++ += *work++;
1246
 
  else if (strncmp(op,"*",1) == 0)
1247
 
    while(n--)
1248
 
      *x++ *= *work++;
1249
 
  else if (strncmp(op,"max",3) == 0)
1250
 
    while(n--) {
1251
 
      *x = ARMCI_MAX(*x, *work);
1252
 
      x++; work++;
1253
 
    }
1254
 
  else if (strncmp(op,"min",3) == 0)
1255
 
    while(n--) {
1256
 
      *x = ARMCI_MIN(*x, *work);
1257
 
      x++; work++;
1258
 
    }
1259
 
  else if (strncmp(op,"absmax",6) == 0)
1260
 
    while(n--) {
1261
 
      register float x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1262
 
      *x = ARMCI_MAX(x1, x2);
1263
 
      x++; work++;
1264
 
    }
1265
 
  else if (strncmp(op,"absmin",6) == 0)
1266
 
    while(n--) {
1267
 
      register float x1 = ARMCI_ABS(*x), x2 = ARMCI_ABS(*work);
1268
 
      *x = ARMCI_MIN(x1, x2);
1269
 
      x++; work++;
1270
 
    }
1271
 
  else
1272
 
    armci_die("fdoop: unknown operation requested", n);
1273
 
}
1274
 
 
1275
 
/*\ reduce operation for float x= op(work,work2)
1276
 
\*/
1277
 
static void fdoop2(int n, char *op, float *x, float* work, float* work2)
1278
 
{
1279
 
  if (strncmp(op,"+",1) == 0)
1280
 
    while(n--)
1281
 
      *x++ = *work++ + *work2++;
1282
 
  else if (strncmp(op,"*",1) == 0)
1283
 
    while(n--)
1284
 
      *x++ = *work++ *  *work2++;
1285
 
  else if (strncmp(op,"max",3) == 0)
1286
 
    while(n--) {
1287
 
      *x = ARMCI_MAX(*work2, *work);
1288
 
      x++; work++; work2++;
1289
 
    }
1290
 
  else if (strncmp(op,"min",3) == 0)
1291
 
    while(n--) {
1292
 
      *x = ARMCI_MIN(*work2, *work);
1293
 
      x++; work++; work2++;
1294
 
    }
1295
 
  else if (strncmp(op,"absmax",6) == 0)
1296
 
    while(n--) {
1297
 
      register float x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1298
 
      *x = ARMCI_MAX(x1, x2);
1299
 
      x++; work++; work2++;
1300
 
    }
1301
 
  else if (strncmp(op,"absmin",6) == 0)
1302
 
    while(n--) {
1303
 
      register float x1 = ARMCI_ABS(*work), x2 = ARMCI_ABS(*work2);
1304
 
      *x = ARMCI_MIN(x1, x2);
1305
 
      x++; work++; work2++;
1306
 
    }
1307
 
  else
1308
 
    armci_die("fdoop2: unknown operation requested", n);
1309
 
}
1310
 
 
1311
 
/*\ combine array of longs/ints accross all processes
1312
 
\*/
1313
 
void armci_msg_gop_scope(int scope, void *x, int n, char* op, int type)
1314
 
{
1315
 
int root, up, left, right, size;
1316
 
int tag=ARMCI_TAG;
1317
 
int ndo, len, lenmes, orign =n, ratio;
1318
 
void *origx =x;
1319
 
    if(!x)armci_die("armci_msg_gop: NULL pointer", n);
1320
 
    if(work==NULL)_allocate_mem_for_work();
1321
 
#ifdef BGML
1322
 
   BGML_Dt dt;
1323
 
   BGML_Op theop;
1324
 
 
1325
 
   if(n > 0 && (strncmp(op, "+", 1) == 0) && (type==ARMCI_INT || type==ARMCI_DOUBLE))
1326
 
   {
1327
 
      theop=BGML_SUM;
1328
 
      if(type==ARMCI_INT)
1329
 
         dt=BGML_SIGNED_INT;
1330
 
      else if(type==ARMCI_DOUBLE)
1331
 
         dt=BGML_DOUBLE;
1332
 
      BGTr_Allreduce(origx, x, n, dt, theop, -1, PCLASS);
1333
 
   }
1334
 
   else if(n > 0 && (strncmp(op, "max", 3) == 0) && (type==ARMCI_INT || type==ARMCI_DOUBLE))
1335
 
   {
1336
 
      theop=BGML_MAX;
1337
 
      if(type==ARMCI_INT)
1338
 
         dt=BGML_SIGNED_INT;
1339
 
      else if(type==ARMCI_DOUBLE)
1340
 
         dt=BGML_DOUBLE;
1341
 
      BGTr_Allreduce(origx, x, n, dt, theop, -1, PCLASS);
1342
 
   }
1343
 
   else if(n > 0 && (strncmp(op, "min", 3) == 0) && (type==ARMCI_INT || type==ARMCI_DOUBLE))
1344
 
   {
1345
 
      theop=BGML_MIN;
1346
 
      if(type==ARMCI_INT)
1347
 
         dt=BGML_SIGNED_INT;
1348
 
      else if(type==ARMCI_DOUBLE)
1349
 
         dt=BGML_DOUBLE;
1350
 
      BGTr_Allreduce(origx, x, n, dt, theop, -1, PCLASS);
1351
 
   }
1352
 
   else
1353
 
#endif
1354
 
  {
1355
 
    armci_msg_bintree(scope, &root, &up, &left, &right);
1356
 
 
1357
 
    if(type==ARMCI_INT) size = sizeof(int);
1358
 
    else if(type==ARMCI_LONG) size = sizeof(long);
1359
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1360
 
    else if(type==ARMCI_FLOAT) size = sizeof(float);
1361
 
    else size = sizeof(double);
1362
 
 
1363
 
    ratio = sizeof(double)/size;
1364
 
    
1365
 
    while ((ndo = (n<=BUF_SIZE*ratio) ? n : BUF_SIZE*ratio)) {
1366
 
         len = lenmes = ndo*size;
1367
 
 
1368
 
         if (left > -1) {
1369
 
           armci_msg_rcv(tag, lwork, len, &lenmes, left);
1370
 
           if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
1371
 
           else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
1372
 
           else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x,llwork);
1373
 
           else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
1374
 
           else ddoop(ndo, op, (double*)x, work);
1375
 
         }
1376
 
 
1377
 
         if (right > -1) {
1378
 
           armci_msg_rcv(tag, lwork, len, &lenmes, right);
1379
 
           if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
1380
 
           else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
1381
 
           else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x,llwork);
1382
 
           else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
1383
 
           else ddoop(ndo, op, (double*)x, work);
1384
 
         }
1385
 
         if (armci_me != root && up!=-1) armci_msg_snd(tag, x, len, up);
1386
 
 
1387
 
         n -=ndo;
1388
 
         x = len + (char*)x;
1389
 
     }
1390
 
 
1391
 
     /* Now, root broadcasts the result down the binary tree */
1392
 
     len = orign*size;
1393
 
     armci_msg_bcast_scope(scope, origx, len, root);
1394
 
   }
1395
 
}
1396
 
 
1397
 
 
1398
 
void armci_msg_reduce_scope(int scope, void *x, int n, char* op, int type)
1399
 
{
1400
 
int root, up, left, right, size;
1401
 
int tag=ARMCI_TAG;
1402
 
int ndo, len, lenmes, ratio;
1403
 
    if(!x)armci_die("armci_msg_gop: NULL pointer", n);
1404
 
    if(work==NULL)_allocate_mem_for_work();
1405
 
 
1406
 
    armci_msg_bintree(scope, &root, &up, &left, &right);
1407
 
 
1408
 
    if(type==ARMCI_INT) size = sizeof(int);
1409
 
    else if(type==ARMCI_LONG) size = sizeof(long);
1410
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1411
 
    else if(type==ARMCI_FLOAT) size = sizeof(float);
1412
 
    else size = sizeof(double);
1413
 
 
1414
 
    ratio = sizeof(double)/size;
1415
 
   
1416
 
    while ((ndo = (n<=BUF_SIZE*ratio) ? n : BUF_SIZE*ratio)) {
1417
 
         len = lenmes = ndo*size;
1418
 
 
1419
 
         if (left > -1) {
1420
 
           armci_msg_rcv(tag, lwork, len, &lenmes, left);
1421
 
           if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
1422
 
           else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
1423
 
           else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x,llwork);
1424
 
           else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
1425
 
           else ddoop(ndo, op, (double*)x, work);
1426
 
         }
1427
 
 
1428
 
         if (right > -1) {
1429
 
           armci_msg_rcv(tag, lwork, len, &lenmes, right);
1430
 
           if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
1431
 
           else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
1432
 
           else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x,llwork);
1433
 
           else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
1434
 
           else ddoop(ndo, op, (double*)x, work);
1435
 
         }
1436
 
         if (armci_me != root && up!=-1) armci_msg_snd(tag, x, len, up);
1437
 
 
1438
 
         n -=ndo;
1439
 
         x = len + (char*)x;
1440
 
     }
1441
 
}
1442
 
 
1443
 
static void gop(int type, int ndo, char* op, void *x, void *work)
1444
 
{
1445
 
     if(type==ARMCI_INT) idoop(ndo, op, (int*)x, (int*)work);
1446
 
     else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, (long*)work);
1447
 
     else if(type==ARMCI_LONG_LONG) lldoop(ndo, op, (long long*)x, (long long*)work);
1448
 
     else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, (float*)work);
1449
 
     else ddoop(ndo, op, (double*)x, (double*)work);
1450
 
}
1451
 
 
1452
 
 
1453
 
static void gop2(int type, int ndo, char* op, void *x, void *work, void *work2)
1454
 
{
1455
 
#if 0
1456
 
     int size;
1457
 
     if(type==ARMCI_INT) size = sizeof(int);
1458
 
     else if(type==ARMCI_LONG) size = sizeof(long);
1459
 
     else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1460
 
     else if(type==ARMCI_FLOAT) size = sizeof(float);
1461
 
     else size = sizeof(double);
1462
 
 
1463
 
     armci_copy(work2,x,ndo*size);
1464
 
 
1465
 
     if(type==ARMCI_INT) idoop(ndo, op, (int*)x, (int*)work);
1466
 
     else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, (long*)work);
1467
 
     else if(type==ARMCI_LONG_LONG) lldoop(ndo, op, (long long*)x, (long long*)work);
1468
 
     else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, (float*)work);
1469
 
     else ddoop(ndo, op, (double*)x, (double*)work);
1470
 
#else
1471
 
     if(type==ARMCI_INT) idoop2(ndo, op, (int*)x, (int*)work, (int*)work2);
1472
 
     else if(type==ARMCI_LONG)ldoop2(ndo,op,(long*)x,(long*)work,(long*)work2);
1473
 
     else if(type==ARMCI_LONG_LONG) lldoop2(ndo,op,(long long*)x,(long long*)work,(long long*)work2);
1474
 
     else if(type==ARMCI_FLOAT)fdoop2(ndo,op,(float*)x,(float*)work,(float*)work2);
1475
 
     else ddoop2(ndo, op, (double*)x, (double*)work,(double*)work2);
1476
 
#endif
1477
 
}
1478
 
 
1479
 
 
1480
 
 
1481
 
 
1482
 
/*\ shared memory based reduction for a single SMP node
1483
 
\*/
1484
 
static void armci_smp_reduce(void *x, int n, char* op, int type)
1485
 
{
1486
 
int root, up, left, right, size;
1487
 
int ndo, len, lenmes, ratio;
1488
 
int nslave = armci_clus_info[armci_clus_me].nslave; 
1489
 
 
1490
 
    if(nslave<2) return; /* nothing to do */
1491
 
 
1492
 
    if(!x)armci_die("armci_msg_gop: NULL pointer", n);
1493
 
 
1494
 
    armci_msg_bintree(SCOPE_NODE, &root, &up, &left, &right);
1495
 
 
1496
 
    if(type==ARMCI_INT) size = sizeof(int);
1497
 
    else if(type==ARMCI_LONG) size = sizeof(long);
1498
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1499
 
    else if(type==ARMCI_FLOAT) size = sizeof(float); 
1500
 
    else size = sizeof(double);
1501
 
    ratio = sizeof(double)/size;
1502
 
    
1503
 
    while ((ndo = (n<=BUF_SIZE*ratio) ? n : BUF_SIZE*ratio)) {
1504
 
       len = lenmes = ndo*size;
1505
 
 
1506
 
       armci_util_wait_int(&GOP_BUF(armci_me)->a.flag, EMPTY, 100);
1507
 
 
1508
 
#if 1
1509
 
        if(left<0 && right<0) armci_copy(x,GOP_BUF(armci_me)->array,len); 
1510
 
 
1511
 
       /*  version oblivious to the order of data arrival */
1512
 
       {
1513
 
          int need_left = left >-1;
1514
 
          int need_right = right >-1;
1515
 
          int from, first =1, maxspin=100, count=0;
1516
 
          bufstruct *b;
1517
 
          
1518
 
          while(need_left || need_right){
1519
 
               from =-1;
1520
 
               if(need_left && GOP_BUF(left)->a.flag == FULL){
1521
 
                  from =left;
1522
 
                  need_left =0;
1523
 
               }else if(need_right && GOP_BUF(right)->a.flag == FULL) {
1524
 
                  from =right;
1525
 
                  need_right =0;
1526
 
               }
1527
 
               if(from != -1){
1528
 
                  b = GOP_BUF(from);
1529
 
#if 1
1530
 
                  if(armci_me == root) gop(type, ndo, op, x, b->array);
1531
 
                  else {
1532
 
                    if(first)
1533
 
                      gop2(type, ndo, op, GOP_BUF(armci_me)->array, b->array,x);
1534
 
                    else
1535
 
                      gop(type, ndo, op, GOP_BUF(armci_me)->array, b->array);
1536
 
                  }
1537
 
                  first =0;
1538
 
#else
1539
 
                  gop(type, ndo, op, GOP_BUF(armci_me)->array, b->array);
1540
 
#endif
1541
 
                  SET_SHM_FLAG(&( b->a.flag),empty);
1542
 
               }else  if((++count)<maxspin) armci_util_spin(count,_gop_buffer);
1543
 
                      else{cpu_yield();count =0; }
1544
 
          }
1545
 
       }
1546
 
#else
1547
 
               
1548
 
       armci_copy(x,GOP_BUF(armci_me)->array,len);
1549
 
 
1550
 
       /*  this version requires a specific order of data arrival */
1551
 
       if (left >-1) {
1552
 
         while(GOP_BUF(left)->a.flag != FULL) cpu_yield();
1553
 
         gop(type, ndo, op, GOP_BUF(armci_me)->array, GOP_BUF(left)->array);
1554
 
         SET_SHM_FLAG(&( GOP_BUF(left)->a.flag),empty);
1555
 
       }
1556
 
       if (right >-1 ) {
1557
 
         while(GOP_BUF(right)->a.flag != FULL) cpu_yield();
1558
 
         gop(type, ndo, op, GOP_BUF(armci_me)->array, GOP_BUF(right)->array);
1559
 
         GOP_BUF(right)->a.flag = EMPTY;
1560
 
       }
1561
 
#endif
1562
 
 
1563
 
       if (armci_me != root ) {
1564
 
           SET_SHM_FLAG(&(GOP_BUF(armci_me)->a.flag),full);
1565
 
       }
1566
 
#if 0
1567
 
        else
1568
 
           /* NOTE:  this copy can be eliminated in a cluster configuration */
1569
 
           armci_copy(GOP_BUF(armci_me)->array,x,len);
1570
 
#endif
1571
 
 
1572
 
       n -=ndo;
1573
 
       x = len + (char*)x;
1574
 
    }  
1575
 
}
1576
 
 
1577
 
void _armci_msg_binomial_reduce(void *x, int n, char* op, int type){
1578
 
    int root = armci_clus_info[0].master;
1579
 
    int i,next_node,next;
1580
 
    int size, ratio, ndo, lenmes,len;
1581
 
/*    int my_rank,root_rank,next_rank; */
1582
 
    if(work==NULL)_allocate_mem_for_work();
1583
 
    if(armci_me!=armci_master)return;
1584
 
    if(type==ARMCI_INT) size = sizeof(int);
1585
 
    else if(type==ARMCI_LONG) size = sizeof(long);
1586
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1587
 
    else if(type==ARMCI_FLOAT) size = sizeof(float);
1588
 
    else size = sizeof(double);
1589
 
    ratio = sizeof(double)/size;
1590
 
   
1591
 
    while ((ndo = (n<=BUF_SIZE*ratio) ? n : BUF_SIZE*ratio)) {
1592
 
       int snd_proc=armci_clus_me,flag=1,diff=1;
1593
 
 
1594
 
       len = lenmes = ndo*size;
1595
 
       if(armci_me!=root){
1596
 
         while(!(snd_proc & flag)){
1597
 
           diff=diff<<1;
1598
 
           flag=flag<<1;
1599
 
         }
1600
 
         snd_proc = armci_clus_info[armci_clus_me-diff].master;
1601
 
       }    
1602
 
       else
1603
 
         diff = Lp2;
1604
 
 
1605
 
       /*printf("\n%d: %d diff>>1 = %d\n",armci_me,Lp2,diff>>1);*/
1606
 
       for(i=diff>>1;i>=1;i=i>>1){
1607
 
         next=i^armci_clus_me;
1608
 
         if(next>=0 && next<armci_nclus){
1609
 
           next_node = armci_clus_info[next].master;
1610
 
           armci_msg_rcv(ARMCI_TAG, lwork,len,&lenmes,next_node);
1611
 
           if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
1612
 
           else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
1613
 
           else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x,llwork);
1614
 
           else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
1615
 
           else ddoop(ndo, op, (double*)x, work);
1616
 
           /*printf("\n%d: recvd from %d \n",armci_me,next_node);*/
1617
 
         }
1618
 
       }
1619
 
       /*if(armci_me!=root){
1620
 
          printf("\n%d: send to  %d \n",armci_me,snd_proc);
1621
 
          fflush(stdout);
1622
 
       }*/
1623
 
       if(armci_me!=root)
1624
 
         armci_msg_snd(ARMCI_TAG,x,len,snd_proc);
1625
 
       n -=ndo;
1626
 
       x = len + (char*)x;
1627
 
    }
1628
 
}
1629
 
 
1630
 
void armci_msg_reduce(void *x, int n, char* op, int type)
1631
 
{
1632
 
    if(DEBUG_)printf("%d reduce  %d\n",armci_me, n);
1633
 
    /* intra-node operation */
1634
 
 
1635
 
#if 1
1636
 
    if(_armci_gop_shmem) 
1637
 
       armci_smp_reduce(x, n, op, type);
1638
 
    else
1639
 
#endif
1640
 
    armci_msg_reduce_scope(SCOPE_NODE, x, n, op, type);
1641
 
 
1642
 
    /* inter-node operation between masters */
1643
 
    if(armci_nclus>1){
1644
 
#ifdef LAPI
1645
 
       if(_armci_gop_init)
1646
 
         _armci_msg_binomial_reduce(x,n,op,type);
1647
 
       else
1648
 
#endif
1649
 
         armci_msg_reduce_scope(SCOPE_MASTERS, x, n, op, type);
1650
 
    }
1651
 
}
1652
 
 
1653
 
 
1654
 
static void armci_msg_gop2(void *x, int n, char* op, int type)
1655
 
{
1656
 
int size, root=0;
1657
 
     if(work==NULL)_allocate_mem_for_work();
1658
 
     if(type==ARMCI_INT) size = sizeof(int);
1659
 
     else if(type==ARMCI_LONG) size = sizeof(long);
1660
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
1661
 
     else if(type==ARMCI_FLOAT) size = sizeof(float);
1662
 
     else size = sizeof(double);
1663
 
#ifdef BGML /*optimize what we can at the message layer */
1664
 
      void *origx=x;
1665
 
      BGML_Dt dt;
1666
 
      BGML_Op rop;
1667
 
 
1668
 
      if(n>0 && (strncmp(op, "+", 1) == 0))
1669
 
      {
1670
 
         rop=BGML_SUM;
1671
 
         if(type == ARMCI_INT)
1672
 
         {
1673
 
            dt=BGML_SIGNED_INT;
1674
 
            BGTr_Allreduce(origx, x, n, dt, rop, -1, 3);
1675
 
         }
1676
 
         else if(type == ARMCI_LONG || type == ARMCI_LONG_LONG)
1677
 
         {
1678
 
            armci_msg_reduce(x, n, op, type);
1679
 
            armci_msg_bcast(x, size*n, root);
1680
 
/*            dt=BGML_UNSIGNED_LONG; */
1681
 
/*            BGTr_Allreduce(origx, x, n, dt, rop, -1, 3);*/
1682
 
         }
1683
 
         else if(type == ARMCI_DOUBLE)
1684
 
         {
1685
 
            dt=BGML_DOUBLE;
1686
 
            BGTr_Allreduce(origx, x, n, dt, rop, -1, 3);
1687
 
         }
1688
 
         else if(type == ARMCI_FLOAT)
1689
 
         {
1690
 
            armci_msg_reduce(x, n, op, type);
1691
 
            armci_msg_bcast(x, size*n, root);
1692
 
         }
1693
 
         else
1694
 
         {
1695
 
            fprintf(stderr,"Unknown data type\n");
1696
 
            exit(1);
1697
 
         }
1698
 
      }
1699
 
 
1700
 
      else if(n>0 && ((strncmp(op, "max", 3) == 0) || (strncmp(op, "min", 3) ==0 )))
1701
 
      {
1702
 
         if(strncmp(op, "max", 3) == 0)
1703
 
            rop=BGML_MAX;
1704
 
         else
1705
 
            rop=BGML_MIN;
1706
 
 
1707
 
         if(type == ARMCI_INT)
1708
 
            dt=BGML_SIGNED_INT;
1709
 
         else if(type == ARMCI_DOUBLE)
1710
 
            dt=BGML_DOUBLE;
1711
 
         else if(type == ARMCI_FLOAT)
1712
 
            dt=BGML_FLOAT;
1713
 
         else if(type == ARMCI_LONG)
1714
 
            dt=BGML_SIGNED_LONG;
1715
 
         else if(type == ARMCI_LONG_LONG)
1716
 
         {
1717
 
            armci_msg_reduce(x, n, op, type);
1718
 
            armci_msg_bcast(x, size*n, root);
1719
 
         }
1720
 
         else
1721
 
         {
1722
 
            fprintf(stderr,"Unknown data type\n");
1723
 
            exit(1);
1724
 
         }
1725
 
         if(type != ARMCI_LONG_LONG)
1726
 
           BGTr_Allreduce(origx, x, n, dt, rop, -1, 3);
1727
 
      }
1728
 
 
1729
 
      else
1730
 
#endif
1731
 
   { /* brackets needed for final gelse clause of bgml */
1732
 
 
1733
 
     armci_msg_reduce(x, n, op, type);
1734
 
     armci_msg_bcast(x, size*n, root);
1735
 
   }
1736
 
}
1737
 
 
1738
 
 
1739
 
static void armci_sel(int type, char *op, void *x, void* work, int n)
1740
 
{
1741
 
int selected=0;
1742
 
  switch (type) {
1743
 
  case ARMCI_INT:
1744
 
     if(strncmp(op,"min",3) == 0){ 
1745
 
        if(*(int*)x > *(int*)work) selected=1;
1746
 
     }else
1747
 
        if(*(int*)x < *(int*)work) selected=1;
1748
 
     break;
1749
 
  case ARMCI_LONG:
1750
 
     if(strncmp(op,"min",3) == 0){ 
1751
 
        if(*(long*)x > *(long*)work) selected=1;
1752
 
     }else
1753
 
        if(*(long*)x < *(long*)work) selected=1;
1754
 
     break;
1755
 
  case ARMCI_LONG_LONG:
1756
 
     if(strncmp(op,"min",3) == 0){ 
1757
 
        if(*(long long*)x > *(long long*)work) selected=1;
1758
 
     }else
1759
 
        if(*(long long*)x < *(long long*)work) selected=1;
1760
 
     break;
1761
 
  case ARMCI_FLOAT:
1762
 
     if(strncmp(op,"min",3) == 0){ 
1763
 
        if(*(float*)x > *(float*)work) selected=1;
1764
 
     }else
1765
 
        if(*(float*)x < *(float*)work) selected=1;
1766
 
     break;
1767
 
  default:
1768
 
     if(strncmp(op,"min",3) == 0){
1769
 
        if(*(double*)x > *(double*)work) selected=1;
1770
 
     }else
1771
 
        if(*(double*)x < *(double*)work) selected=1;
1772
 
  }
1773
 
  if(selected)armci_copy(work,x, n);
1774
 
}
1775
 
   
1776
 
 
1777
 
 
1778
 
/*\ global for  op with extra info 
1779
 
\*/
1780
 
void armci_msg_sel_scope(int scope, void *x, int n, char* op, int type, int contribute)
1781
 
{
1782
 
int root, up, left, right;
1783
 
int tag=ARMCI_TAG;
1784
 
int len, lenmes, min;
1785
 
 
1786
 
    min = (strncmp(op,"min",3) == 0);
1787
 
    if(!min && (strncmp(op,"max",3) != 0))
1788
 
            armci_die("armci_msg_gop_info: operation not supported ", 0);
1789
 
 
1790
 
    if(!x)armci_die("armci_msg_gop_info: NULL pointer", n);
1791
 
 
1792
 
    if(n>((int)INFO_BUF_SIZE))armci_die("armci_msg_gop_info: info too large",n);
1793
 
 
1794
 
    len = lenmes = n;
1795
 
 
1796
 
    armci_msg_bintree(scope, &root, &up, &left, &right);
1797
 
 
1798
 
    if (left > -1) {
1799
 
 
1800
 
        /* receive into work if contributing otherwise into x */
1801
 
        if(contribute)armci_msg_rcv(tag, work, len, &lenmes, left);
1802
 
        else armci_msg_rcv(tag, x, len, &lenmes, left);
1803
 
 
1804
 
        if(lenmes){
1805
 
           if(contribute) armci_sel(type, op, x, work, n);
1806
 
           else contribute =1; /* now we got data to pass */ 
1807
 
        }
1808
 
    }
1809
 
 
1810
 
    if (right > -1) {
1811
 
        /* receive into work if contributing otherwise into x */
1812
 
        if(contribute) armci_msg_rcv(tag, work, len, &lenmes, right);
1813
 
        else armci_msg_rcv(tag, x, len, &lenmes, right);
1814
 
 
1815
 
        if(lenmes){
1816
 
           if(contribute) armci_sel(type, op, x, work, n);
1817
 
           else contribute =1; /* now we got data to pass */ 
1818
 
        }
1819
 
    }
1820
 
 
1821
 
    if (armci_me != root){
1822
 
       if(contribute) armci_msg_snd(tag, x, len, up);
1823
 
       else armci_msg_snd(tag, x, 0, up); /* send 0 bytes */
1824
 
    }
1825
 
 
1826
 
    /* Now, root broadcasts the result down the binary tree */
1827
 
    armci_msg_bcast_scope(scope, x, n, root);
1828
 
}
1829
 
 
1830
 
 
1831
 
/*\ combine array of longs/ints/doubles accross all processes
1832
 
\*/
1833
 
 
1834
 
#if defined(NEC)
1835
 
 
1836
 
void armci_msg_igop(int *x, int n, char* op)
1837
 
{ armci_msg_gop_scope(SCOPE_ALL,x, n, op, ARMCI_INT); }
1838
 
 
1839
 
void armci_msg_lgop(long *x, int n, char* op)
1840
 
{ armci_msg_gop_scope(SCOPE_ALL,x, n, op, ARMCI_LONG); }
1841
 
 
1842
 
void armci_msg_llgop(long long *x, int n, char* op)
1843
 
{ armci_msg_gop_scope(SCOPE_ALL,x, n, op, ARMCI_LONG_LONG); }
1844
 
 
1845
 
void armci_msg_dgop(double *x, int n, char* op)
1846
 
{ armci_msg_gop_scope(SCOPE_ALL,x, n, op, ARMCI_DOUBLE); }
1847
 
 
1848
 
void armci_msg_fgop (float *x, int n, char* op)
1849
 
{ armci_msg_gop_scope(SCOPE_ALL,x, n, op, ARMCI_FLOAT);}
1850
 
 
1851
 
#else
1852
 
void armci_msg_igop(int *x, int n, char* op) { armci_msg_gop2(x, n, op, ARMCI_INT); }
1853
 
void armci_msg_lgop(long *x, int n, char* op) { armci_msg_gop2(x, n, op, ARMCI_LONG); }
1854
 
void armci_msg_llgop(long long *x, int n, char* op) { armci_msg_gop2(x, n, op, ARMCI_LONG_LONG); }
1855
 
void armci_msg_fgop(float *x, int n, char* op) { armci_msg_gop2(x, n, op, ARMCI_FLOAT); }
1856
 
void armci_msg_dgop(double *x, int n, char* op) { armci_msg_gop2(x, n, op, ARMCI_DOUBLE); }
1857
 
#endif
1858
 
 
1859
 
 
1860
 
/*\ add array of longs/ints within the same cluster node
1861
 
\*/
1862
 
void armci_msg_clus_igop(int *x, int n, char* op)
1863
 
{ armci_msg_gop_scope(SCOPE_NODE,x, n, op, ARMCI_INT); }
1864
 
 
1865
 
void armci_msg_clus_lgop(long *x, int n, char* op)
1866
 
{ armci_msg_gop_scope(SCOPE_NODE,x, n, op, ARMCI_LONG); }
1867
 
 
1868
 
void armci_msg_clus_llgop(long long *x, int n, char* op)
1869
 
{ armci_msg_gop_scope(SCOPE_NODE,x, n, op, ARMCI_LONG_LONG); }
1870
 
 
1871
 
void armci_msg_clus_fgop(float *x, int n, char* op)
1872
 
{ armci_msg_gop_scope(SCOPE_NODE,x, n, op, ARMCI_FLOAT); }
1873
 
 
1874
 
void armci_msg_clus_dgop_scope(double *x, int n, char* op)
1875
 
{ armci_msg_gop_scope(SCOPE_NODE,x, n, op, ARMCI_DOUBLE); }
1876
 
 
1877
 
 
1878
 
 
1879
 
void armci_exchange_address(void *ptr_ar[], int n)
1880
 
{
1881
 
  int ratio = sizeof(void*)/sizeof(int);
1882
 
/*
1883
 
  armci_msg_lgop((long*)ptr_ar, n, "+");
1884
 
*/
1885
 
  if(DEBUG_)printf("%d: exchanging %ld ratio=%d\n",armci_me,(long)ptr_ar[armci_me],ratio);
1886
 
 
1887
 
  armci_msg_gop2(ptr_ar, n*ratio, "+",ARMCI_INT);
1888
 
}
1889
 
 
1890
 
/**
1891
 
 * ********************* Begin ARMCI Groups Code ****************************
1892
 
 * NOTE: This part is MPI dependent (i.e. ifdef MPI)
1893
 
 */
1894
 
#ifdef MPI
1895
 
MPI_Comm armci_group_comm(ARMCI_Group *group)
1896
 
{
1897
 
#ifdef ARMCI_GROUP
1898
 
    return MPI_COMM_NULL;
1899
 
#else
1900
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(group);
1901
 
    return (MPI_Comm)igroup->icomm;
1902
 
#endif
1903
 
}
1904
 
 
1905
 
void parmci_msg_group_barrier(ARMCI_Group *group)
1906
 
{
1907
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(group);
1908
 
    
1909
 
#ifdef ARMCI_GROUP
1910
 
 {
1911
 
   int val=0;
1912
 
   armci_msg_group_igop(&val, 1, "+", group);
1913
 
 }
1914
 
#else
1915
 
    MPI_Barrier((MPI_Comm)(igroup->icomm));
1916
 
#endif
1917
 
}
1918
 
 
1919
 
#ifdef ARMCI_GROUP
1920
 
extern void ARMCI_Bcast_(void *buffer, int len, int root, ARMCI_Group *group);
1921
 
#else
1922
 
extern void ARMCI_Bcast_(void *buffer, int len, int root, ARMCI_Comm comm);
1923
 
#endif
1924
 
void armci_grp_clus_brdcst(void *buf, int len, int grp_master,
1925
 
                           int grp_clus_nproc, ARMCI_Group *mastergroup) {
1926
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(mastergroup);
1927
 
    int i, *pid_list, root=0;
1928
 
#ifdef ARMCI_GROUP
1929
 
    ARMCI_Group group;
1930
 
#else
1931
 
    MPI_Group group_world;
1932
 
    MPI_Group group;
1933
 
    MPI_Comm comm;
1934
 
#endif
1935
 
 
1936
 
    /* create a communicator for the processes with in a node */
1937
 
    pid_list = (int *)malloc(grp_clus_nproc*sizeof(int));
1938
 
    for(i=0; i<grp_clus_nproc; i++)  pid_list[i] = grp_master+i;
1939
 
 
1940
 
 
1941
 
#ifdef ARMCI_GROUP
1942
 
    ARMCI_Group_create_child(grp_clus_nproc, pid_list, &group, mastergroup);
1943
 
    ARMCI_Bcast_(buf, len, root, &group);
1944
 
    ARMCI_Group_free(&group);
1945
 
#else
1946
 
    /* why?*/
1947
 
    MPI_Comm_group((MPI_Comm)(igroup->icomm), &group_world);
1948
 
    MPI_Group_incl(group_world, grp_clus_nproc, pid_list, &group);
1949
 
 
1950
 
    MPI_Comm_create((MPI_Comm)(igroup->icomm), (MPI_Group)group,
1951
 
                    (MPI_Comm*)&comm);
1952
 
 
1953
 
    /* Broadcast within the node (for this sub group of processes) */
1954
 
    ARMCI_Bcast_(buf, len, root, comm);
1955
 
 
1956
 
    free(pid_list);
1957
 
    MPI_Comm_free(&comm);     /* free the temporary communicator */
1958
 
    MPI_Group_free(&group);
1959
 
#endif
1960
 
}
1961
 
 
1962
 
 
1963
 
/* to avoid warning */
1964
 
extern int ARMCI_Absolute_id(ARMCI_Group *group,int group_rank);
1965
 
 
1966
 
void armci_msg_group_bintree(int scope, int* Root, int *Up, int *Left, int *Right,
1967
 
                             ARMCI_Group *group)
1968
 
{
1969
 
    int root, up, left, right, index, nproc,grp_clus_me,grp_me,grp_master,grp_nproc;
1970
 
    armci_grp_attr_t *grp_attr=ARMCI_Group_getattr(group);
1971
 
    grp_me = grp_attr->grp_me;
1972
 
    grp_clus_me = grp_attr->grp_clus_me;
1973
 
    grp_master = grp_attr->grp_clus_info[grp_clus_me].master;
1974
 
    ARMCI_Group_size(group, &grp_nproc);
1975
 
    if(scope == SCOPE_NODE){
1976
 
       root  = grp_attr->grp_clus_info[grp_clus_me].master;
1977
 
       nproc = grp_attr->grp_clus_info[grp_clus_me].nslave;
1978
 
       index = grp_me - root;
1979
 
       up    = (index-1)/2 + root; if( up < root) up = -1;
1980
 
       left  = 2*index + 1 + root; if(left >= root+nproc) left = -1;
1981
 
       right = 2*index + 2 + root; if(right >= root+nproc)right = -1;
1982
 
    }else if(scope ==SCOPE_MASTERS){
1983
 
       root  = grp_attr->grp_clus_info[0].master;
1984
 
       nproc = grp_attr->grp_nclus;
1985
 
       if(grp_me != grp_master){up = -1; left = -1; right = -1; }
1986
 
       else{
1987
 
          index = grp_clus_me - root;
1988
 
          up    = (index-1)/2 + root;
1989
 
          up = ( up < root)? -1: grp_attr->grp_clus_info[up].master;
1990
 
          left = 2*index + 1 + root;
1991
 
          left =( left >= root+nproc)?-1:grp_attr->grp_clus_info[left].master;
1992
 
          right= 2*index + 2 + root;
1993
 
          right=( right>=root+nproc)?-1:grp_attr->grp_clus_info[right].master;
1994
 
       }
1995
 
    }else{
1996
 
       root  = 0;
1997
 
       nproc = grp_nproc;
1998
 
       index = grp_me - root;
1999
 
       up    = (index-1)/2 + root; if( up < root) up = -1;
2000
 
       left  = 2*index + 1 + root; if(left >= root+nproc) left = -1;
2001
 
       right = 2*index + 2 + root; if(right >= root+nproc)right = -1;
2002
 
    }
2003
 
    
2004
 
    *Up = (up==-1)?up:ARMCI_Absolute_id(group,up);
2005
 
    *Left = (left==-1)?left:ARMCI_Absolute_id(group,left);
2006
 
    *Right = (right==-1)?right:ARMCI_Absolute_id(group,right);
2007
 
    *Root = (root==-1)?root:ARMCI_Absolute_id(group,root);
2008
 
}
2009
 
 
2010
 
void armci_msg_group_bcast_scope(int scope, void *buf, int len, int root,
2011
 
                                 ARMCI_Group *group)
2012
 
{
2013
 
    int up, left, right, Root;
2014
 
    int grp_me;
2015
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(group);
2016
 
 
2017
 
    if(!buf)armci_die("armci_msg_bcast: NULL pointer", len);
2018
 
 
2019
 
    if(!group)armci_msg_bcast_scope(scope,buf,len,root);
2020
 
    else grp_me = igroup->grp_attr.grp_me;
2021
 
    armci_msg_group_bintree(scope, &Root, &up, &left, &right,group);
2022
 
 
2023
 
    if(root !=Root){
2024
 
       if(armci_me == root) armci_msg_snd(ARMCI_TAG, buf,len, Root);
2025
 
       if(armci_me ==Root) armci_msg_rcv(ARMCI_TAG, buf, len, NULL, root);
2026
 
    }
2027
 
 
2028
 
    /* printf("%d: scope=%d left=%d right=%d up=%d\n",armci_me, scope,
2029
 
       left, right, up);*/
2030
 
 
2031
 
    if(armci_me != Root && up!=-1) armci_msg_rcv(ARMCI_TAG, buf, len, NULL, up);
2032
 
                                     if (left > -1)  armci_msg_snd(ARMCI_TAG, buf, len, left);
2033
 
                                     if (right > -1) armci_msg_snd(ARMCI_TAG, buf, len, right);
2034
 
}
2035
 
 
2036
 
void
2037
 
armci_msg_group_gop_scope(int scope, void *x, int n, char* op, int type,
2038
 
                          ARMCI_Group *group)
2039
 
{
2040
 
    int root, up, left, right, size;
2041
 
    int tag=ARMCI_TAG,grp_me;
2042
 
    int ndo, len, lenmes, orign =n, ratio;
2043
 
    void *origx =x;
2044
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(group);
2045
 
 
2046
 
    if(!group)armci_msg_gop_scope(scope,x,n,op,type);
2047
 
    else grp_me = igroup->grp_attr.grp_me;
2048
 
    if(!x)armci_die("armci_msg_gop: NULL pointer", n);
2049
 
    if(work==NULL)_allocate_mem_for_work();
2050
 
 
2051
 
    armci_msg_group_bintree(scope, &root, &up, &left, &right,group);
2052
 
 
2053
 
    if(type==ARMCI_INT) size = sizeof(int);
2054
 
    else if(type==ARMCI_LONG) size = sizeof(long);
2055
 
    else if(type==ARMCI_LONG_LONG) size = sizeof(long long);
2056
 
    else if(type==ARMCI_FLOAT) size = sizeof(float);
2057
 
    else size = sizeof(double);
2058
 
 
2059
 
    ratio = sizeof(double)/size;
2060
 
 
2061
 
    while ((ndo = (n<=BUF_SIZE*ratio) ? n : BUF_SIZE*ratio)) {
2062
 
       len = lenmes = ndo*size;
2063
 
 
2064
 
       if (left > -1) {
2065
 
          armci_msg_rcv(tag, lwork, len, &lenmes, left);
2066
 
          if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
2067
 
          else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
2068
 
          else if(type==ARMCI_LONG_LONG) lldoop(ndo, op, (long long*)x,llwork);
2069
 
          else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
2070
 
          else ddoop(ndo, op, (double*)x, work);
2071
 
       }
2072
 
 
2073
 
       if (right > -1) {
2074
 
          armci_msg_rcv(tag, lwork, len, &lenmes, right);
2075
 
          if(type==ARMCI_INT) idoop(ndo, op, (int*)x, iwork);
2076
 
          else if(type==ARMCI_LONG) ldoop(ndo, op, (long*)x, lwork);
2077
 
          else if(type==ARMCI_LONG_LONG) lldoop(ndo, op,(long long*)x, llwork);
2078
 
          else if(type==ARMCI_FLOAT) fdoop(ndo, op, (float*)x, fwork);
2079
 
          else ddoop(ndo, op, (double*)x, work);
2080
 
       }
2081
 
       if (armci_me != root && up!=-1) armci_msg_snd(tag, x, len, up);
2082
 
 
2083
 
       n -=ndo;
2084
 
       x = len + (char*)x;
2085
 
    }
2086
 
 
2087
 
    /* Now, root broadcasts the result down the binary tree */
2088
 
    len = orign*size;
2089
 
    armci_msg_group_bcast_scope(scope, origx, len, root,group);
2090
 
}
2091
 
 
2092
 
void armci_exchange_address_grp(void *ptr_arr[], int n, ARMCI_Group *group)
2093
 
{
2094
 
    int ratio = sizeof(void*)/sizeof(int);
2095
 
    ARMCI_iGroup *igroup = armci_get_igroup_from_group(group);
2096
 
    int grp_me = igroup->grp_attr.grp_me;
2097
 
    if(DEBUG_){
2098
 
       printf("%d: exchanging %ld ratio=%d\n",armci_me,
2099
 
              (long)ptr_arr[grp_me], ratio);
2100
 
    }
2101
 
    armci_msg_group_gop_scope(SCOPE_ALL, ptr_arr, n*ratio,
2102
 
                              "+", ARMCI_INT, group);
2103
 
}
2104
 
 
2105
 
/*\ combine array of longs/ints/doubles accross all processes
2106
 
\*/
2107
 
void armci_msg_group_igop(int *x, int n, char* op, ARMCI_Group *group)
2108
 
{ armci_msg_group_gop_scope(SCOPE_ALL,x, n, op, ARMCI_INT,group); }
2109
 
 
2110
 
void armci_msg_group_lgop(long *x, int n, char* op,ARMCI_Group *group)
2111
 
{ armci_msg_group_gop_scope(SCOPE_ALL,x, n, op, ARMCI_LONG,group); }
2112
 
 
2113
 
void armci_msg_group_llgop(long long *x, int n, char* op,ARMCI_Group *group)
2114
 
{ armci_msg_group_gop_scope(SCOPE_ALL,x, n, op, ARMCI_LONG_LONG,group); }
2115
 
 
2116
 
void armci_msg_group_fgop(float *x, int n, char* op,ARMCI_Group *group)
2117
 
{ armci_msg_group_gop_scope(SCOPE_ALL,x, n, op, ARMCI_FLOAT,group); }
2118
 
 
2119
 
void armci_msg_group_dgop(double *x, int n, char* op,ARMCI_Group *group)
2120
 
{ armci_msg_group_gop_scope(SCOPE_ALL,x, n, op, ARMCI_DOUBLE,group); }
2121
 
 
2122
 
#  endif /* ifdef MPI */
2123
 
/*********************** End ARMCI Groups Code ****************************/
2124
 
 
2125
 
 
2126
 
#ifdef PVM
2127
 
/* set the group name if using PVM */
2128
 
void ARMCI_PVM_Init(char *mpgroup)
2129
 
{
2130
 
#ifdef CRAY
2131
 
    mp_group_name = (char *)NULL;
2132
 
#else
2133
 
    if(mpgroup != NULL) {
2134
 
/*        free(mp_group_name); */
2135
 
        mp_group_name = (char *)malloc(25 * sizeof(char));
2136
 
        strcpy(mp_group_name, mpgroup);
2137
 
    }
2138
 
#endif
2139
 
}
2140
 
#endif