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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src-gemini/pack.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: pack.c,v 1.36.10.1 2006-12-14 13:24:37 manoj Exp $ */
 
6
#include "armcip.h"
 
7
#include <stdio.h>
 
8
 
 
9
#if !defined(ACC_COPY) &&!defined(CRAY_YMP) &&!defined(CYGNUS)&&!defined(CYGWIN) &&!defined(BGML)
 
10
#   define REMOTE_OP 
 
11
#endif
 
12
 
 
13
#if defined(REMOTE_OP) 
 
14
#  define OP_STRIDED armci_rem_strided
 
15
#else
 
16
#  define OP_STRIDED(_a,_b,_c,_d,_e,_f,_g,_h,_i,_delete1,_j,_hdl)\
 
17
                    armci_op_strided(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_hdl)
 
18
#endif
 
19
 
 
20
 
 
21
/*\ determine if patch fits in the ARMCI buffer, and if not 
 
22
 *  at which stride level (patch dim) need to decompose it 
 
23
 *  *fit_level is the value of stride level to perform packing at 
 
24
 *  *nb means number of elements of count[*fit_level] that fit in buf 
 
25
\*/
 
26
static void armci_fit_buffer(int count[], int stride_levels, int* fit_level, 
 
27
                             int *nb, int bufsize)
 
28
{
 
29
   int bytes=1, sbytes=1;
 
30
   int level;
 
31
 
 
32
   /* find out at which stride level BUFFER becomes too small */
 
33
   for(level=0; level<= stride_levels; level++){
 
34
      sbytes = bytes; /* store #bytes at current level to save div cost later */
 
35
      bytes *= count[level];
 
36
      if(bufsize < bytes) break;
 
37
   }
 
38
 
 
39
   /* buffer big enough for entire patch */
 
40
   if(bufsize >= bytes){
 
41
       *fit_level = stride_levels;
 
42
       *nb = count[stride_levels];
 
43
       return;
 
44
   }
 
45
 
 
46
   /* buffer too small */
 
47
   switch (level){
 
48
   case 0: 
 
49
       /* smaller than a single column */
 
50
       *fit_level = 0;
 
51
       *nb = bufsize;
 
52
       break;
 
53
   case -1:   /* one column fits */
 
54
       *fit_level = 0;
 
55
       *nb = sbytes;
 
56
       break;
 
57
   default:
 
58
       /* it could keep nb instances of (level-1)-dimensional patch */
 
59
       *fit_level = level;
 
60
       *nb = bufsize/sbytes;
 
61
   }   
 
62
}
 
63
 
 
64
 
 
65
/*\ The function decomposes a multi-dimensional patch so that it fits in the
 
66
 *  internal ARMCI buffer.
 
67
 *  It works by recursively reducing patch dimension until some portion of the
 
68
 *  subpatch fits in the buffer.
 
69
 *  The recursive process is controlled by "fit_level" and "nb" arguments, 
 
70
 *  which have to be set to -1 at the top-level of the recursion tree.
 
71
 *
 
72
 *  Argument last and variable looplast are used to indicate to sending/packing
 
73
 *  routine that we are dealing with the last portion of the request.
 
74
 *  Due to the recursive nature of packing code, the algorithm is following:
 
75
 *      if last=1  then internal for loop passes 1 for the last chunk
 
76
 *      else it passes 0
 
77
 *  
 
78
\*/
 
79
int armci_pack_strided(int op, void* scale, int proc,
 
80
                       void *src_ptr, int src_stride_arr[],
 
81
                       void* dst_ptr, int dst_stride_arr[],
 
82
                       int count[], int stride_levels, ext_header_t *h,
 
83
                       int fit_level, int nb, int last,armci_ihdl_t nb_handle)
 
84
{
 
85
    int rc=0, sn, bufsize=BUFSIZE,noswap=0;
 
86
    void *src, *dst;
 
87
#ifdef REMOTE_OP
 
88
    int flag=0;
 
89
#else
 
90
    int flag=1;
 
91
#endif
 
92
    int b;
 
93
    static int call_count;
 
94
 
 
95
#ifdef STRIDED_GET_BUFLEN
 
96
    if(op==GET) bufsize=STRIDED_GET_BUFLEN;
 
97
#  ifdef HITACHI
 
98
    else 
 
99
        if(stride_levels || ARMCI_ACC(op)) bufsize=MSG_BUFLEN_SMALL-PAGE_SIZE;
 
100
#  endif
 
101
#endif
 
102
 
 
103
#if (defined(GM_) || defined(VIA_) || defined(VAPI_))
 
104
    /*we cant assume that the entire available buffer will be used for data, 
 
105
      fact that the header and descriptor also go in the same buffer should be
 
106
      considered while packing.
 
107
    */
 
108
    bufsize-=(sizeof(request_header_t)+(MAX_STRIDE_LEVEL+4)*sizeof(int)+2*sizeof(void *));
 
109
#  if defined(PIPE_BUFSIZE) && defined(MAX_PIPELINE_CHUNKS)
 
110
    bufsize-=8*MAX_PIPELINE_CHUNKS;
 
111
#  endif
 
112
#endif
 
113
 
 
114
#ifdef BALANCE_FACTOR
 
115
    /* Added the following for balancing buffers */
 
116
    if(op==PUT){
 
117
        int bytes=1, i;
 
118
        for(i=0; i<= stride_levels; i++)
 
119
                bytes *= count[i];
 
120
        if(bytes > bufsize && bytes/bufsize < 3 && bytes%bufsize < BALANCE_BUFSIZE){
 
121
        /* bytes div bufsize - 1 is to increase the balence factor for 3 buffer case */
 
122
                bufsize = bytes/ (bytes/bufsize - 1 + BALANCE_FACTOR);
 
123
                noswap = 1; /*** yuck: if set to 1, error in buffers.c ***/
 
124
        }
 
125
        bytes = bufsize%8;
 
126
        bufsize -= bytes;
 
127
    }
 
128
#endif
 
129
 
 
130
    /* determine decomposition of the patch to fit in the buffer */
 
131
    if(fit_level<0){
 
132
       armci_fit_buffer(count, stride_levels, &fit_level, &nb, bufsize);
 
133
       last = 1;
 
134
    }
 
135
 
 
136
//  printf("%s [cp]: pack_strided: flag=%d, bufsize=%ld; fit_level=%d; stride_level=%d; nb=%d\n",Portals_ID(),flag,(long) bufsize,fit_level,stride_levels,nb);
 
137
 
 
138
    if(fit_level == stride_levels){
 
139
 
 
140
        /* we can fit subpatch into the buffer */
 
141
        int chunk = count[fit_level];
 
142
        int dst_stride, src_stride;
 
143
 
 
144
        if(nb == chunk){ /* take shortcut when whole patch fits in the buffer */
 
145
           if(h) h->last = last?1:0;
 
146
           if(nb_handle  && call_count ){
 
147
             nb_handle->bufid=NB_MULTI;
 
148
             call_count++;
 
149
           }
 
150
           return(OP_STRIDED(op, scale, proc, src_ptr, src_stride_arr,
 
151
                  dst_ptr,dst_stride_arr,count,stride_levels,h,flag,nb_handle));
 
152
        }
 
153
 
 
154
        if(fit_level){
 
155
           dst_stride = dst_stride_arr[fit_level -1];
 
156
           src_stride = src_stride_arr[fit_level -1];
 
157
        }else{
 
158
           dst_stride = src_stride = 1;
 
159
        }
 
160
        if(op == GET || noswap == 1) b =nb; 
 
161
        else{ b = chunk%nb; if(b==0)b=nb; } /* put smallest piece first */
 
162
 
 
163
        for(sn = 0; sn < chunk; ){
 
164
           src = (char*)src_ptr + src_stride* sn;
 
165
           dst = (char*)dst_ptr + dst_stride* sn;
 
166
           count[fit_level] = ARMCI_MIN(b, chunk-sn); /*modify count for this level*/
 
167
 
 
168
           if(h) h->last = (last && ((sn+b)>=chunk))? 1: 0 ;
 
169
           if(nb_handle)call_count++;
 
170
           rc = OP_STRIDED( op, scale, proc, src, src_stride_arr,
 
171
                           dst,dst_stride_arr,count,fit_level,h,flag,nb_handle);
 
172
           if(rc) break;
 
173
 
 
174
           sn += b;
 
175
           b = nb;
 
176
        }
 
177
        count[fit_level] = chunk; /* restore original count */
 
178
 
 
179
    }
 
180
    else {
 
181
        for(sn = 0; sn < count[stride_levels]; sn++){
 
182
           int looplast =0;
 
183
           src = (char*)src_ptr + src_stride_arr[stride_levels -1]* sn;
 
184
           dst = (char*)dst_ptr + dst_stride_arr[stride_levels -1]* sn;
 
185
 
 
186
           if(last && (sn == count[stride_levels]-1)) looplast =1;
 
187
           rc = armci_pack_strided(op, scale, proc, src, src_stride_arr,
 
188
                                   dst, dst_stride_arr, count, stride_levels -1,
 
189
                                   h,fit_level, nb, looplast,nb_handle);
 
190
           if(rc) return rc;
 
191
        }
 
192
    }
 
193
    if(nb_handle && call_count )
 
194
       nb_handle->bufid=NB_MULTI;
 
195
    return rc;
 
196
}
 
197
 
 
198
/*\ decompose strided data into chunks and call func on each chunk
 
199
\*/
 
200
void armci_dispatch_strided(void *ptr, int stride_arr[], int count[],
 
201
                            int strides, int fit_level, int nb, int bufsize, 
 
202
                            void (*fun)(void*,int*,int*,int,void*), void *arg)
 
203
{
 
204
    int  sn,first_call=0;
 
205
    void *ptr_upd;
 
206
 
 
207
    /* determine decomposition of the patch to fit in the buffer */
 
208
    if(fit_level<0){
 
209
       first_call=1;
 
210
       armci_fit_buffer(count, strides, &fit_level, &nb, bufsize);
 
211
    }
 
212
 
 
213
 
 
214
    if(fit_level == strides){
 
215
 
 
216
        /* we can fit subpatch into the buffer */
 
217
        int chunk = count[fit_level];
 
218
        int stride_upd;
 
219
   
 
220
#       ifdef PIPE_MEDIUM_BUFSIZE_
 
221
          /* for first call we adjust nb for performance in medium request  */
 
222
          if(first_call && strides==0)
 
223
             if(chunk<2*bufsize && chunk>PIPE_MEDIUM_BUFSIZE) 
 
224
                                              nb = PIPE_MEDIUM_BUFSIZE;
 
225
#       endif
 
226
 
 
227
        if(nb == chunk){ /* take shortcut when whole patch fits in the buffer */
 
228
           fun(ptr, stride_arr, count, strides, arg);
 
229
        }
 
230
 
 
231
        if(fit_level)
 
232
           stride_upd = stride_arr[fit_level -1];
 
233
        else
 
234
           stride_upd = 1;
 
235
 
 
236
        for(sn = 0; sn < chunk; sn += nb){
 
237
 
 
238
           ptr_upd = (char*)ptr + stride_upd* sn;
 
239
           count[fit_level] = ARMCI_MIN(nb, chunk-sn); /*modify count for this level*/
 
240
           fun(ptr_upd, stride_arr, count, fit_level, arg);
 
241
        }
 
242
        count[fit_level] = chunk; /* restore original count */
 
243
 
 
244
    }else for(sn = 0; sn < count[strides]; sn++){
 
245
              ptr_upd = (char*)ptr + stride_arr[strides -1]* sn;
 
246
              armci_dispatch_strided(ptr_upd, stride_arr, count, strides -1,
 
247
                                     fit_level, nb, bufsize, fun, arg);
 
248
    }
 
249
}
 
250
 
 
251
/* how much space is needed to move data + reduced descriptor ? */
 
252
int armci_vector_bytes( armci_giov_t darr[], int len)
 
253
{
 
254
int i, bytes=0;
 
255
    for(i=0; i<len; i++){                                   
 
256
        /*       # elements            * (elem size     + dst address ) */
 
257
        bytes += darr[i].ptr_array_len * (darr[i].bytes + sizeof(void*));
 
258
        bytes += 2*sizeof(int); /* ptr_array_len + bytes */
 
259
    }
 
260
    return bytes;
 
261
}
 
262
 
 
263
 
 
264
#define BUFSIZE10 26000 
 
265
#define BUFSIZE1  BUFSIZE
 
266
 
 
267
void armci_split_dscr_array( armci_giov_t darr[], int len,
 
268
                             armci_giov_t* extra, int *nlen, armci_giov_t* save)
 
269
{
 
270
int s;
 
271
int bytes=0, split=0;
 
272
 
 
273
    extra->src_ptr_array=NULL;
 
274
    /* go through the sets looking for set to be split */
 
275
    for(s=0;s<len;s++){
 
276
        int csize;
 
277
 
 
278
        csize  = darr[s].ptr_array_len * (darr[s].bytes + sizeof(void*));
 
279
        csize += 2*sizeof(int); /* ptr_array_len + bytes */
 
280
 
 
281
        if(csize + bytes >BUFSIZE1){
 
282
 
 
283
          split =(BUFSIZE1 -bytes-2*sizeof(int))/(darr[s].bytes +sizeof(void*));
 
284
          if(split == 0) s--; /* no room available - do not split */
 
285
          break;
 
286
 
 
287
        }else bytes+=csize;
 
288
 
 
289
        if(BUFSIZE1 -bytes < 64) break; /* stop here if almost full */
 
290
    }
 
291
 
 
292
    if(s==len)s--; /* adjust loop counter should be < number of sets */ 
 
293
    *nlen = s+1;
 
294
 
 
295
    if(split){
 
296
 
 
297
       /* save the value to be overwritten only if "save" is not filled */ 
 
298
       if(!save->src_ptr_array)*save= darr[s];
 
299
 
 
300
       /* split the set: reduce # of elems, "extra" keeps info for rest of set*/
 
301
       *extra = darr[s];
 
302
       darr[s].ptr_array_len = split;
 
303
       extra->ptr_array_len -= split;
 
304
       extra->src_ptr_array  = &extra->src_ptr_array[split];
 
305
       extra->dst_ptr_array  = &extra->dst_ptr_array[split];
 
306
    }
 
307
 
308
    
 
309
 
 
310
 
 
311
int armci_pack_vector(int op, void *scale, armci_giov_t darr[],int len,
 
312
                      int proc,armci_ihdl_t nb_handle)
 
313
{
 
314
armci_giov_t extra; /* keeps data remainder of set to be processed in chunks */
 
315
armci_giov_t save;  /* keeps original value of set to be processed in chunks */
 
316
armci_giov_t *ndarr; /* points to first array element to be processed now */
 
317
int rc=0, nlen, count=0;
 
318
 
 
319
    ndarr = darr;
 
320
 
 
321
    save.src_ptr_array=NULL; /* indicates that save slot is empty */
 
322
    while(len){
 
323
 
 
324
       armci_split_dscr_array(ndarr, len, &extra, &nlen, &save); 
 
325
#  if defined(REMOTE_OP) 
 
326
       rc = armci_rem_vector(op, scale, ndarr,nlen,proc,0,nb_handle);
 
327
#  else
 
328
       if(ARMCI_ACC(op))rc=armci_acc_vector(op,scale,ndarr,nlen,proc);
 
329
       else rc = armci_copy_vector(op,ndarr,nlen,proc);
 
330
#  endif
 
331
       if(rc) break;
 
332
 
 
333
       /* non-NULL pointer indicates that set was split */
 
334
       if(extra.src_ptr_array){
 
335
 
 
336
         if(nb_handle) {
 
337
           nb_handle->bufid = NB_MULTI; /*can be set multiple times here; but not reset here*/
 
338
         }
 
339
 
 
340
          ndarr[nlen-1]=extra; /* set the pointer to remainder of last set */
 
341
          nlen--; /* since last set not done in full need to process it again */
 
342
 
 
343
       }else{
 
344
 
 
345
          if(save.src_ptr_array){
 
346
             ndarr[0]=save;
 
347
             save.src_ptr_array=NULL; /* indicates that save slot is empty */
 
348
          }
 
349
 
 
350
          if(nlen==0)
 
351
            armci_die("vector packetization problem:buffer too small",BUFSIZE1);
 
352
       }
 
353
 
 
354
       len -=nlen;
 
355
       ndarr +=nlen;
 
356
       count ++;
 
357
    }
 
358
 
 
359
    return rc;
 
360
}