~ubuntu-branches/ubuntu/saucy/nwchem/saucy

« back to all changes in this revision

Viewing changes to src/tools/ga-4-3/examples/armci/features/aggregation/sparse_matvecmul/sparse_matvecmul.c

  • Committer: Package Import Robot
  • Author(s): Michael Banck, Michael Banck, Daniel Leidert
  • Date: 2012-02-09 20:02:41 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120209200241-jgk03qfsphal4ug2
Tags: 6.1-1
* New upstream release.

[ Michael Banck ]
* debian/patches/02_makefile_flags.patch: Updated.
* debian/patches/02_makefile_flags.patch: Use internal blas and lapack code.
* debian/patches/02_makefile_flags.patch: Define GCC4 for LINUX and LINUX64
  (Closes: #632611 and LP: #791308).
* debian/control (Build-Depends): Added openssh-client.
* debian/rules (USE_SCALAPACK, SCALAPACK): Removed variables (Closes:
  #654658).
* debian/rules (LIBDIR, USE_MPIF4, ARMCI_NETWORK): New variables.
* debian/TODO: New file.
* debian/control (Build-Depends): Removed libblas-dev, liblapack-dev and
  libscalapack-mpi-dev.
* debian/patches/04_show_testsuite_diff_output.patch: New patch, shows the
  diff output for failed tests.
* debian/patches/series: Adjusted.
* debian/testsuite: Optionally run all tests if "all" is passed as option.
* debian/rules: Run debian/testsuite with "all" if DEB_BUILD_OPTIONS
  contains "checkall".

[ Daniel Leidert ]
* debian/control: Used wrap-and-sort. Added Vcs-Svn and Vcs-Browser fields.
  (Priority): Moved to extra according to policy section 2.5.
  (Standards-Version): Bumped to 3.9.2.
  (Description): Fixed a typo.
* debian/watch: Added.
* debian/patches/03_hurd-i386_define_path_max.patch: Added.
  - Define MAX_PATH if not defines to fix FTBFS on hurd.
* debian/patches/series: Adjusted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*$id$*/
 
2
#include <stdio.h>
 
3
#include <stdlib.h>
 
4
#include <assert.h>
 
5
 
 
6
#ifdef WIN32
 
7
#  include <windows.h>
 
8
#  define sleep(x) Sleep(1000*(x))
 
9
#else
 
10
#  include <unistd.h>
 
11
#endif
 
12
 
 
13
#if defined(PVM)
 
14
#   include <pvm3.h>
 
15
#   ifdef CRAY
 
16
#     define MPGROUP         (char *)NULL
 
17
#     define MP_INIT(arc,argv)
 
18
#   else
 
19
#     define MPGROUP           "mp_working_group"
 
20
#     define MP_INIT(arc,argv) pvm_init(arc, argv)
 
21
#   endif
 
22
#   define MP_FINALIZE()     pvm_exit()
 
23
#   define MP_TIMER          armci_timer
 
24
#   define MP_BARRIER()      pvm_barrier(MPGROUP,-1)
 
25
#   define MP_MYID(pid)      *(pid)   = pvm_getinst(MPGROUP,pvm_mytid())
 
26
#   define MP_PROCS(pproc)   *(pproc) = (int)pvm_gsize(MPGROUP)
 
27
    void pvm_init(int argc, char *argv[]);
 
28
#elif defined(TCGMSG)
 
29
#   include <sndrcv.h>
 
30
    long tcg_tag =30000;
 
31
#   define MP_BARRIER()      SYNCH_(&tcg_tag)
 
32
#   define MP_INIT(arc,argv) PBEGIN_((argc),(argv))
 
33
#   define MP_FINALIZE()     PEND_()
 
34
#   define MP_MYID(pid)      *(pid)   = (int)NODEID_()
 
35
#   define MP_PROCS(pproc)   *(pproc) = (int)NNODES_()
 
36
#   define MP_TIMER         TCGTIME_
 
37
#else
 
38
#   include <mpi.h>
 
39
#   define MP_BARRIER()      MPI_Barrier(MPI_COMM_WORLD)
 
40
#   define MP_FINALIZE()     MPI_Finalize()
 
41
#   define MP_INIT(arc,argv) MPI_Init(&(argc),&(argv))
 
42
#   define MP_MYID(pid)      MPI_Comm_rank(MPI_COMM_WORLD, (pid))
 
43
#   define MP_PROCS(pproc)   MPI_Comm_size(MPI_COMM_WORLD, (pproc));
 
44
#   define MP_TIMER         MPI_Wtime
 
45
#endif
 
46
 
 
47
#include "armci.h"
 
48
#include "message.h"
 
49
 
 
50
#define DIM1 5
 
51
#define DIM2 3
 
52
#ifdef __sun
 
53
/* Solaris has shared memory shortages in the default system configuration */
 
54
# define DIM3 6
 
55
# define DIM4 5
 
56
# define DIM5 4
 
57
#elif defined(__alpha__)
 
58
# define DIM3 8
 
59
# define DIM4 5
 
60
# define DIM5 6
 
61
#else
 
62
# define DIM3 8
 
63
# define DIM4 9
 
64
# define DIM5 7
 
65
#endif
 
66
#define DIM6 3
 
67
#define DIM7 2
 
68
 
 
69
 
 
70
#define OFF 1
 
71
#define EDIM1 (DIM1+OFF)
 
72
#define EDIM2 (DIM2+OFF)
 
73
#define EDIM3 (DIM3+OFF)
 
74
#define EDIM4 (DIM4+OFF)
 
75
#define EDIM5 (DIM5+OFF)
 
76
#define EDIM6 (DIM6+OFF)
 
77
#define EDIM7 (DIM7+OFF)
 
78
 
 
79
#define DIMS 4
 
80
#define MAXDIMS 7
 
81
#define MAX_DIM_VAL 50 
 
82
#define LOOP 200
 
83
 
 
84
#define BASE 100.
 
85
#define MAXPROC 128
 
86
#define TIMES 100
 
87
 
 
88
#ifdef CRAY
 
89
# define ELEMS 800
 
90
#else
 
91
# define ELEMS 200
 
92
#endif
 
93
 
 
94
/***************************** macros ************************/
 
95
#define COPY(src, dst, bytes) memcpy((dst),(src),(bytes))
 
96
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
 
97
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
 
98
#define ABS(a) (((a) <0) ? -(a) : (a))
 
99
 
 
100
#define ROW      65536
 
101
#define COL      ROW   /* square matrices only for the time being */
 
102
 
 
103
/***************************** global data *******************/
 
104
int me, nproc;
 
105
short int fortran_indexing=0;
 
106
static int proc_row_list[MAXPROC];/*no of rows owned by each process - accumulated*/
 
107
static int proc_nz_list[MAXPROC]; /*no of non-zeros owned by each process */
 
108
 
 
109
#ifdef PVM
 
110
void pvm_init(int argc, char *argv[])
 
111
{
 
112
    int mytid, mygid, ctid[MAXPROC];
 
113
    int np, i;
 
114
 
 
115
    mytid = pvm_mytid();
 
116
    if((argc != 2) && (argc != 1)) goto usage;
 
117
    if(argc == 1) np = 1;
 
118
    if(argc == 2)
 
119
        if((np = atoi(argv[1])) < 1) goto usage;
 
120
    if(np > MAXPROC) goto usage;
 
121
 
 
122
    mygid = pvm_joingroup(MPGROUP);
 
123
 
 
124
    if(np > 1)
 
125
        if (mygid == 0) 
 
126
            i = pvm_spawn(argv[0], argv+1, 0, "", np-1, ctid);
 
127
 
 
128
    while(pvm_gsize(MPGROUP) < np) sleep(1);
 
129
 
 
130
    /* sync */
 
131
    pvm_barrier(MPGROUP, np);
 
132
    
 
133
    printf("PVM initialization done!\n");
 
134
    
 
135
    return;
 
136
 
 
137
usage:
 
138
    fprintf(stderr, "usage: %s <nproc>\n", argv[0]);
 
139
    pvm_exit();
 
140
    exit(-1);
 
141
}
 
142
#endif
 
143
          
 
144
void create_array(void *a[], int elem_size, int ndim, int dims[])
 
145
{
 
146
     int bytes=elem_size, i, rc;
 
147
 
 
148
     assert(ndim<=MAXDIMS);
 
149
     for(i=0;i<ndim;i++)bytes*=dims[i];
 
150
 
 
151
     rc = ARMCI_Malloc(a, bytes);
 
152
     assert(rc==0);
 
153
     
 
154
     assert(a[me]);
 
155
     
 
156
}
 
157
 
 
158
void destroy_array(void *ptr[])
 
159
{
 
160
    MP_BARRIER();
 
161
 
 
162
    assert(!ARMCI_Free(ptr[me]));
 
163
}
 
164
 
 
165
static void verify_list(int *proc_row_list) {
 
166
  int i;
 
167
  printf("\nVERIFY: %d: No of rows = %d\n\n", 0, proc_row_list[0]);
 
168
  for(i=1; i<nproc; i++)
 
169
    printf("\nVERIFY: %d: No of rows = %d\n\n", i, proc_row_list[i]-proc_row_list[i-1]);    
 
170
  fflush(stdout);
 
171
}
 
172
 
 
173
static void load_balance(int n, int non_zero, int *row_ind_tmp) {
 
174
 
 
175
  int proc_id, i, local_nz, local_nz_acc, A, B;
 
176
 
 
177
  local_nz = local_nz_acc = non_zero/nproc;
 
178
 
 
179
  /* number of rows owned by each process is stored in proc_row_list. This 
 
180
     is supposed to be well load balanced, so that each process has almost 
 
181
     same number of non-zero elements */
 
182
  proc_id = 0;
 
183
  if(me==0) printf("local_nz = %d\n", local_nz);
 
184
  for(i=0; i<n; i++) { /* as # of entries in row_ind_tmp = n+1 */
 
185
    if(row_ind_tmp[i] < local_nz_acc && row_ind_tmp[i+1] >= local_nz_acc) {
 
186
      proc_row_list[proc_id++] = i+1;
 
187
      local_nz_acc = local_nz*(proc_id+1);
 
188
      if(proc_id == nproc-1) local_nz_acc = non_zero;
 
189
      if(me==0 && proc_id<nproc) printf("local_nz = %d\n", local_nz_acc);
 
190
    }
 
191
  }
 
192
 
 
193
  proc_row_list[nproc-1] = n;
 
194
 
 
195
  for(i=0; i<nproc; i++) {
 
196
    A = (i==0) ? 0: proc_row_list[i-1];/* # of entries in row_ind_tmp is n+1*/ 
 
197
    B = proc_row_list[i];
 
198
    proc_nz_list[i] = row_ind_tmp[B]-row_ind_tmp[A];
 
199
  }
 
200
  
 
201
  if(proc_id != nproc) 
 
202
    ARMCI_Error("Error while preparing Process Row list", proc_id-1);
 
203
 
 
204
#if 1
 
205
  if(me==0) verify_list(proc_row_list);
 
206
#endif
 
207
 
 
208
}
 
209
 
 
210
static int sparse_initialize(int *n, int *non_zero, int **row_ind, 
 
211
                             int **col_ind, double **values, double **vec,
 
212
                             double **svec) {
 
213
  
 
214
  int i, j, rc, max, *row_ind_tmp, *tmp_indices;
 
215
  double *tmp_values;
 
216
  unsigned long len;
 
217
  FILE *fp;
 
218
 
 
219
  /* Broadcast order of matrix */
 
220
  if(me==0) {
 
221
    if((fp=fopen("Sparse-MPI/av41092.rua.data", "r")) == NULL)
 
222
      ARMCI_Error("Error: Input file not found", me);
 
223
    fortran_indexing = 1; /* This is 1 for Harwell-Boeing format matrices */
 
224
    fscanf(fp, "%d", n);
 
225
    if(*n%nproc) 
 
226
      ARMCI_Error("# of rows is not divisible by # of processors", nproc);
 
227
    if(*n > ROW) 
 
228
      ARMCI_Error("order is greater than defined variable ROW", ROW);
 
229
  }
 
230
  len = sizeof(int);
 
231
  armci_msg_brdcst(n, len, 0);  
 
232
 
 
233
  /* Broad cast number of non_zeros */
 
234
  if(me==0) fscanf(fp, "%d", non_zero);
 
235
  armci_msg_brdcst(non_zero, len, 0); 
 
236
 
 
237
  /* Broadcast row indices */
 
238
  len = (*n+1)*sizeof(int);
 
239
  row_ind_tmp = (int *)malloc(len);
 
240
  if(me==0)for(i=0; i<*n+1; i++) {
 
241
    fscanf(fp, "%d", &row_ind_tmp[i]);
 
242
    if(fortran_indexing) --row_ind_tmp[i];
 
243
  }
 
244
  armci_msg_brdcst(row_ind_tmp, len, 0);  
 
245
  
 
246
  load_balance(*n, *non_zero, row_ind_tmp);
 
247
  
 
248
  /* find how much temporary storage is needed at the maximum */
 
249
  if(me==0) {
 
250
    for(max=-1,j=0;j<nproc;j++) if(max<proc_nz_list[j]) max=proc_nz_list[j];
 
251
    if(max<0) ARMCI_Error(" max cannot be negative", max);
 
252
  }
 
253
  
 
254
  /* Broadcast the maximum number of elements */
 
255
  len = sizeof(int);
 
256
  armci_msg_brdcst(&max, len, 0); 
 
257
 
 
258
  /* create the Sparse MAtrix Array */
 
259
  if(me==0) printf("  Creating ValueArray (CompressedSparseMatrix) ...\n\n");
 
260
  create_array((void**)col_ind, sizeof(int), 1, &max);
 
261
   
 
262
  /* create the column subscript array */
 
263
  if(me==0) printf("  Creating Column Subscript Array ... \n\n");
 
264
  create_array((void**)values, sizeof(double), 1, &max);
 
265
 
 
266
  /* create the x-vector and the solution vector */
 
267
  if(me==0) printf("  Creating Vectors ... \n\n");
 
268
  create_array((void**)vec,  sizeof(double),1, &max);
 
269
  create_array((void**)svec, sizeof(double),1, &max);
 
270
  MP_BARRIER();
 
271
 
 
272
  
 
273
  /* Process 0 distributes the column indices and non_zero values to 
 
274
     respective processors*/
 
275
  if(me == 0) {
 
276
    tmp_indices = (int *)malloc(max*sizeof(int));
 
277
    tmp_values  = (double *)malloc(max*sizeof(double));
 
278
    
 
279
    for(j=0; j<nproc; j++) {
 
280
      for(i=0; i<proc_nz_list[j]; i++) {
 
281
        fscanf(fp, "%d", &tmp_indices[i]); 
 
282
        if(fortran_indexing) --tmp_indices[i];
 
283
      }
 
284
      /* rc = fread(tmp_indices, sizeof(int), proc_nz_list[j], fp); */
 
285
      if((rc=ARMCI_Put(tmp_indices, col_ind[j], proc_nz_list[j]*sizeof(int), j)))
 
286
        ARMCI_Error("armci_nbput failed\n",rc);
 
287
    }
 
288
    for(j=0; j<nproc; j++) {
 
289
      for(i=0; i<proc_nz_list[j]; i++) fscanf(fp, "%lf", &tmp_values[i]);
 
290
      if((rc=ARMCI_Put(tmp_values, values[j], proc_nz_list[j]*sizeof(double), j)))
 
291
        ARMCI_Error("armci_nbput failed\n",rc);
 
292
    }
 
293
  }
 
294
  ARMCI_AllFence(); MP_BARRIER();ARMCI_AllFence();
 
295
 
 
296
  /* initializing x-vector */
 
297
  if(me==0) for(i=0;i<proc_nz_list[me]; i++) vec[me][i] = (i+1);
 
298
  else for(i=0;i<proc_nz_list[me];i++) vec[me][i]=me*proc_nz_list[me-1]+(i+1);
 
299
 
 
300
#if 0
 
301
  if(me==0) {
 
302
    printf("max = %d\n", max);
 
303
    for(i=0; i<max; i++)  printf("%.1lf ", values[me][i]);
 
304
    printf("\n");
 
305
  }
 
306
#endif
 
307
 
 
308
  *row_ind = row_ind_tmp;
 
309
  if(me==0) {
 
310
    free(tmp_indices);
 
311
    free(tmp_values);
 
312
    fclose(fp);
 
313
  }
 
314
  return 0;
 
315
}
 
316
 
 
317
static int compare(const void *p1, const void *p2) {
 
318
  int i = *((int *)p1);
 
319
  int j = *((int *)p2);
 
320
  
 
321
  if (i > j) return (1);
 
322
  if (i < j) return (-1);
 
323
  return (0);
 
324
}
 
325
 
 
326
static int count = -1;
 
327
static armci_hdl_t gHandle[MAXPROC];
 
328
static int prev_proc = -1;
 
329
 
 
330
static void get_data(int n, int start, int end, double *vec_local, 
 
331
                    double **vec) {
 
332
  int i, j, rc, bytes, offset;
 
333
  int proc_start, proc_end, idx_start, idx_end;
 
334
 
 
335
  proc_start = proc_end = -1;
 
336
  for(i=0; i<nproc; i++) {
 
337
    if(proc_start<0 && proc_row_list[i]>start) proc_start = i;
 
338
    if(proc_end<0 && proc_row_list[i]>end) proc_end = i;    
 
339
  }
 
340
  if(proc_start<0 || proc_end<0) ARMCI_Error("Invalid Process Ids", -1);
 
341
 
 
342
  for(i=proc_start; i<=proc_end; i++) {
 
343
    if(i==proc_start) idx_start = start;
 
344
    else { if(i==0) idx_start=0; else idx_start = proc_row_list[i-1];}
 
345
    if(i==proc_end) idx_end = end;
 
346
    else idx_end = proc_row_list[i]-1;
 
347
   
 
348
    if(i!=prev_proc) {
 
349
      ++count;   prev_proc = i;  
 
350
      ARMCI_INIT_HANDLE(&gHandle[count]);
 
351
      ARMCI_SET_AGGREGATE_HANDLE(&gHandle[count]);
 
352
    }
 
353
    
 
354
    if(i==0) offset=0; else offset = proc_row_list[i-1];
 
355
    if(i==me) { /* local */
 
356
      for(j=idx_start; j<=idx_end; j++) vec_local[j] = vec[me][j-offset];
 
357
    }
 
358
    else {     /* remote */
 
359
      bytes = (idx_end-idx_start+1)*sizeof(double);
 
360
      vec_local[idx_start] = -1;
 
361
#if 0
 
362
      if((rc=ARMCI_Get(&vec[i][idx_start-offset], &vec_local[idx_start],
 
363
                       bytes, i)))
 
364
#else
 
365
      if((rc=ARMCI_NbGet(&vec[i][idx_start-offset], &vec_local[idx_start],
 
366
                       bytes, i, &gHandle[count])))
 
367
#endif
 
368
        ARMCI_Error("armci_nbget failed\n",rc);
 
369
    }
 
370
  }
 
371
}
 
372
 
 
373
static void sparse_multiply(int n, int non_zero, int *row_ind, int **col_ind, 
 
374
                    double **values, double **vec, double **svec) {
 
375
  
 
376
  int i, j, k, num_elements, offset, *tmp_indices;
 
377
  double start_time, comm_time, comp_time, v, vec_local[COL];
 
378
  int start, end, prev, nrows, idx;
 
379
 
 
380
#if 0
 
381
  /* ---- Sequential Case ----  */
 
382
   for(i=0; i<n; i++) {
 
383
     svec[me][i] = 0;
 
384
     for(k=row_ind[i]; k<row_ind[i+1]; k++) {
 
385
       j = col_ind[me][k];
 
386
       v = values[me][k];
 
387
       svec[me][i] += v*vec[me][j];
 
388
       printf("%.1lf %.1lf\n", v, vec[me][j]);
 
389
     }
 
390
   }
 
391
   for(i=0; i<n; i++) printf("%.1lf ", svec[me][i]);
 
392
   printf("\n");
 
393
#else
 
394
 
 
395
  num_elements = proc_nz_list[me];
 
396
  printf("num_elements = %d\n", num_elements);
 
397
  tmp_indices = (int *)malloc(num_elements*sizeof(int));
 
398
  for(i=0; i<num_elements; i++) tmp_indices[i] = col_ind[me][i];
 
399
  qsort(tmp_indices, num_elements, sizeof(int), compare);
 
400
 
 
401
  start_time = MP_TIMER();
 
402
 
 
403
  /* get the required portion of vector you need to local array */
 
404
  start = prev = tmp_indices[0];
 
405
  for(i=1; i<num_elements; i++) {
 
406
    if(tmp_indices[i]>prev+1) {
 
407
      end = prev;
 
408
      get_data(n, start, end, vec_local, vec);
 
409
      start = prev = tmp_indices[i];
 
410
    }
 
411
    else prev = tmp_indices[i];
 
412
  }
 
413
  get_data(n, start, prev, vec_local, vec);
 
414
 
 
415
#if 1
 
416
  if(count>=0) for(i=0; i<=count; i++) ARMCI_Wait(&gHandle[i]);
 
417
#endif
 
418
 
 
419
  comm_time = MP_TIMER() - start_time;
 
420
  start_time = MP_TIMER();   
 
421
 
 
422
  /* Perform Matrix-Vector multiply and store the result in
 
423
     solution vector - "svec[]" */
 
424
 
 
425
  if(me==0) { nrows = proc_row_list[me]; offset = row_ind[0]; }
 
426
  else { 
 
427
    nrows = proc_row_list[me]-proc_row_list[me-1]; 
 
428
    offset = row_ind[proc_row_list[me-1]]; 
 
429
  }
 
430
  /* printf("%d: My total Work = %d\n", me, nrows); */
 
431
 
 
432
  for(i=0; i<nrows; i++) { /* loop over rows owned by me */
 
433
    svec[me][i] = 0;
 
434
    if(me==0) idx = i; else idx = proc_row_list[me-1] + i;
 
435
    for(k=row_ind[idx]; k<row_ind[idx+1]; k++) {
 
436
      j = col_ind[me][k-offset];
 
437
      v = values[me][k-offset];
 
438
      svec[me][i] += v*vec_local[j];
 
439
    }
 
440
  }
 
441
  comp_time = MP_TIMER()-start_time;
 
442
  printf("%d: %lf + %lf = %lf  (count = %d)\n", me, comm_time, comp_time, 
 
443
         comm_time+comp_time, count+1);
 
444
#endif
 
445
}
 
446
 
 
447
static void gather_solution_vector(double **svec) {
 
448
#if 0
 
449
  double y[COL];
 
450
  if((rc=ARMCI_Get(&vec[i][idx_start-offset], &vec_local[idx_start],
 
451
                   bytes, i)))
 
452
    ARMCI_Error("armci_nbget failed\n",rc);
 
453
#endif
 
454
}
 
455
 
 
456
static void test_sparse() {
 
457
  
 
458
    int *col_ind[MAXPROC];
 
459
    double *values[MAXPROC], *vec[MAXPROC], *svec[MAXPROC], start_time;
 
460
    int n, non_zero, *row_ind;
 
461
 
 
462
    sparse_initialize(&n, &non_zero, &row_ind, col_ind, values, vec, svec);
 
463
    MP_BARRIER();
 
464
 
 
465
    start_time = MP_TIMER();
 
466
    sparse_multiply(n, non_zero, row_ind, col_ind, values, vec, svec);
 
467
    /* printf("%d: Timetaken = %lf\n", me, MP_TIMER()-start_time); */
 
468
    MP_BARRIER();
 
469
    
 
470
    if(me==0) gather_solution_vector(svec);
 
471
    
 
472
    if(me==0){printf("O.K.\n"); fflush(stdout);}
 
473
    destroy_array((void **)vec);
 
474
}
 
475
 
 
476
 
 
477
/* we need to rename main if linking with frt compiler */
 
478
#ifdef FUJITSU_FRT
 
479
#define main MAIN__
 
480
#endif
 
481
 
 
482
int main(int argc, char* argv[])
 
483
{
 
484
 
 
485
    MP_INIT(argc, argv);
 
486
    MP_PROCS(&nproc);
 
487
    MP_MYID(&me);
 
488
 
 
489
/*    printf("nproc = %d, me = %d\n", nproc, me);*/
 
490
    
 
491
    if(nproc>MAXPROC && me==0)
 
492
       ARMCI_Error("Test works for up to %d processors\n",MAXPROC);
 
493
 
 
494
    if(me==0){
 
495
       printf("ARMCI test program (%d processes)\n",nproc); 
 
496
       fflush(stdout);
 
497
       sleep(1);
 
498
    }
 
499
    
 
500
    ARMCI_Init();
 
501
 
 
502
    if(me==0){
 
503
      printf("\n  Performing Sparse Matrix-Vector Multiplication ...\n\n");
 
504
      fflush(stdout);
 
505
    }
 
506
    test_sparse();
 
507
    
 
508
    ARMCI_AllFence();
 
509
    MP_BARRIER();
 
510
    if(me==0){printf("\nSuccess!!\n"); fflush(stdout);}
 
511
    sleep(2);
 
512
        
 
513
    MP_BARRIER();
 
514
    ARMCI_Finalize();
 
515
    MP_FINALIZE();
 
516
    return(0);
 
517
}