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

« back to all changes in this revision

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