Advertisement
Guest User

Untitled

a guest
Mar 25th, 2017
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 32.66 KB | None | 0 0
  1. /*************************************************************************
  2.  *                                                                       *
  3.  *       N  A  S     P A R A L L E L     B E N C H M A R K S  3.3        *
  4.  *                                                                       *
  5.  *                      O p e n M P     V E R S I O N                    *
  6.  *                                                                       *
  7.  *                                  I S                                  *
  8.  *                                                                       *
  9.  *************************************************************************
  10.  *                                                                       *
  11.  *   This benchmark is an OpenMP version of the NPB IS code.             *
  12.  *   It is described in NAS Technical Report 99-011.                     *
  13.  *                                                                       *
  14.  *   Permission to use, copy, distribute and modify this software        *
  15.  *   for any purpose with or without fee is hereby granted.  We          *
  16.  *   request, however, that all derived work reference the NAS           *
  17.  *   Parallel Benchmarks 3.3. This software is provided "as is"          *
  18.  *   without express or implied warranty.                                *
  19.  *                                                                       *
  20.  *   Information on NPB 3.3, including the technical report, the         *
  21.  *   original specifications, source code, results and information       *
  22.  *   on how to submit new results, is available at:                      *
  23.  *                                                                       *
  24.  *          http://www.nas.nasa.gov/Software/NPB/                        *
  25.  *                                                                       *
  26.  *   Send comments or suggestions to  npb@nas.nasa.gov                   *
  27.  *                                                                       *
  28.  *         NAS Parallel Benchmarks Group                                 *
  29.  *         NASA Ames Research Center                                     *
  30.  *         Mail Stop: T27A-1                                             *
  31.  *         Moffett Field, CA   94035-1000                                *
  32.  *                                                                       *
  33.  *         E-mail:  npb@nas.nasa.gov                                     *
  34.  *         Fax:     (650) 604-3957                                       *
  35.  *                                                                       *
  36.  *************************************************************************
  37.  *                                                                       *
  38.  *   Author: M. Yarrow                                                   *
  39.  *           H. Jin                                                      *
  40.  *                                                                       *
  41.  *************************************************************************/
  42.  
  43. #include "npbparams.h"
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #ifdef _OPENMP
  47. #include <omp.h>
  48. #endif
  49.  
  50.  
  51. /*****************************************************************/
  52. /* For serial IS, buckets are not really req'd to solve NPB1 IS  */
  53. /* spec, but their use on some machines improves performance, on */
  54. /* other machines the use of buckets compromises performance,    */
  55. /* probably because it is extra computation which is not req'd.  */
  56. /* (Note: Mechanism not understood, probably cache related)      */
  57. /* Example:  SP2-66MhzWN:  50% speedup with buckets              */
  58. /* Example:  SGI Indy5000: 50% slowdown with buckets             */
  59. /* Example:  SGI O2000:   400% slowdown with buckets (Wow!)      */
  60. /*****************************************************************/
  61. /* To disable the use of buckets, comment out the following line */
  62. #define USE_BUCKETS
  63.  
  64. /* Uncomment below for cyclic schedule */
  65. /*#define SCHED_CYCLIC*/
  66.  
  67.  
  68. /******************/
  69. /* default values */
  70. /******************/
  71. #ifndef CLASS
  72. #define CLASS 'S'
  73. #endif
  74.  
  75.  
  76. /*************/
  77. /*  CLASS S  */
  78. /*************/
  79. #if CLASS == 'S'
  80. #define  TOTAL_KEYS_LOG_2    16
  81. #define  MAX_KEY_LOG_2       11
  82. #define  NUM_BUCKETS_LOG_2   9
  83. #endif
  84.  
  85.  
  86. /*************/
  87. /*  CLASS W  */
  88. /*************/
  89. #if CLASS == 'W'
  90. #define  TOTAL_KEYS_LOG_2    20
  91. #define  MAX_KEY_LOG_2       16
  92. #define  NUM_BUCKETS_LOG_2   10
  93. #endif
  94.  
  95. /*************/
  96. /*  CLASS A  */
  97. /*************/
  98. #if CLASS == 'A'
  99. #define  TOTAL_KEYS_LOG_2    23
  100. #define  MAX_KEY_LOG_2       19
  101. #define  NUM_BUCKETS_LOG_2   10
  102. #endif
  103.  
  104.  
  105. /*************/
  106. /*  CLASS B  */
  107. /*************/
  108. #if CLASS == 'B'
  109. #define  TOTAL_KEYS_LOG_2    25
  110. #define  MAX_KEY_LOG_2       21
  111. #define  NUM_BUCKETS_LOG_2   10
  112. #endif
  113.  
  114.  
  115. /*************/
  116. /*  CLASS C  */
  117. /*************/
  118. #if CLASS == 'C'
  119. #define  TOTAL_KEYS_LOG_2    27
  120. #define  MAX_KEY_LOG_2       23
  121. #define  NUM_BUCKETS_LOG_2   10
  122. #endif
  123.  
  124.  
  125. /*************/
  126. /*  CLASS D  */
  127. /*************/
  128. #if CLASS == 'D'
  129. #define  TOTAL_KEYS_LOG_2    31
  130. #define  MAX_KEY_LOG_2       27
  131. #define  NUM_BUCKETS_LOG_2   10
  132. #endif
  133.  
  134.  
  135. #if CLASS == 'D'
  136. #define  TOTAL_KEYS          (1L << TOTAL_KEYS_LOG_2)
  137. #else
  138. #define  TOTAL_KEYS          (1 << TOTAL_KEYS_LOG_2)
  139. #endif
  140. #define  MAX_KEY             (1 << MAX_KEY_LOG_2)
  141. #define  NUM_BUCKETS         (1 << NUM_BUCKETS_LOG_2)
  142. #define  NUM_KEYS            TOTAL_KEYS
  143. #define  SIZE_OF_BUFFERS     NUM_KEYS  
  144.                                            
  145.  
  146. #define  MAX_ITERATIONS      10
  147. #define  TEST_ARRAY_SIZE     5
  148.  
  149.  
  150. /*************************************/
  151. /* Typedef: if necessary, change the */
  152. /* size of int here by changing the  */
  153. /* int type to, say, long            */
  154. /*************************************/
  155. #if CLASS == 'D'
  156. typedef  long INT_TYPE;
  157. #else
  158. typedef  int  INT_TYPE;
  159. #endif
  160.  
  161.  
  162. /********************/
  163. /* Some global info */
  164. /********************/
  165. INT_TYPE *key_buff_ptr_global;         /* used by full_verify to get */
  166.                                        /* copies of rank info        */
  167.  
  168. int      passed_verification;
  169.                                  
  170.  
  171. /************************************/
  172. /* These are the three main arrays. */
  173. /* See SIZE_OF_BUFFERS def above    */
  174. /************************************/
  175. INT_TYPE key_array[SIZE_OF_BUFFERS],    
  176.          key_buff1[MAX_KEY],
  177.          key_buff2[SIZE_OF_BUFFERS],
  178.          partial_verify_vals[TEST_ARRAY_SIZE],
  179.          **key_buff1_aptr = NULL;
  180.  
  181. #ifdef USE_BUCKETS
  182. INT_TYPE **bucket_size,
  183.          bucket_ptrs[NUM_BUCKETS];
  184. #pragma omp threadprivate(bucket_ptrs)
  185. #endif
  186.  
  187.  
  188. /**********************/
  189. /* Partial verif info */
  190. /**********************/
  191. INT_TYPE test_index_array[TEST_ARRAY_SIZE],
  192.          test_rank_array[TEST_ARRAY_SIZE],
  193.  
  194.          S_test_index_array[TEST_ARRAY_SIZE] =
  195.                              {48427,17148,23627,62548,4431},
  196.          S_test_rank_array[TEST_ARRAY_SIZE] =
  197.                              {0,18,346,64917,65463},
  198.  
  199.          W_test_index_array[TEST_ARRAY_SIZE] =
  200.                              {357773,934767,875723,898999,404505},
  201.          W_test_rank_array[TEST_ARRAY_SIZE] =
  202.                              {1249,11698,1039987,1043896,1048018},
  203.  
  204.          A_test_index_array[TEST_ARRAY_SIZE] =
  205.                              {2112377,662041,5336171,3642833,4250760},
  206.          A_test_rank_array[TEST_ARRAY_SIZE] =
  207.                              {104,17523,123928,8288932,8388264},
  208.  
  209.          B_test_index_array[TEST_ARRAY_SIZE] =
  210.                              {41869,812306,5102857,18232239,26860214},
  211.          B_test_rank_array[TEST_ARRAY_SIZE] =
  212.                              {33422937,10244,59149,33135281,99},
  213.  
  214.          C_test_index_array[TEST_ARRAY_SIZE] =
  215.                              {44172927,72999161,74326391,129606274,21736814},
  216.          C_test_rank_array[TEST_ARRAY_SIZE] =
  217.                              {61147,882988,266290,133997595,133525895},
  218.  
  219.          D_test_index_array[TEST_ARRAY_SIZE] =
  220.                              {1317351170,995930646,1157283250,1503301535,1453734525},
  221.          D_test_rank_array[TEST_ARRAY_SIZE] =
  222.                              {1,36538729,1978098519,2145192618,2147425337};
  223.  
  224.  
  225. /***********************/
  226. /* function prototypes */
  227. /***********************/
  228. double  randlc( double *X, double *A );
  229.  
  230. void full_verify( void );
  231.  
  232. void c_print_results( char   *name,
  233.                       char   class,
  234.                       int    n1,
  235.                       int    n2,
  236.                       int    n3,
  237.                       int    niter,
  238.                       double t,
  239.                       double mops,
  240.               char   *optype,
  241.                       int    passed_verification,
  242.                       char   *npbversion,
  243.                       char   *compiletime,
  244.                       char   *cc,
  245.                       char   *clink,
  246.                       char   *c_lib,
  247.                       char   *c_inc,
  248.                       char   *cflags,
  249.                       char   *clinkflags );
  250.  
  251.  
  252. void    timer_clear( int n );
  253. void    timer_start( int n );
  254. void    timer_stop( int n );
  255. double  timer_read( int n );
  256.  
  257.  
  258. /*
  259.  *    FUNCTION RANDLC (X, A)
  260.  *
  261.  *  This routine returns a uniform pseudorandom double precision number in the
  262.  *  range (0, 1) by using the linear congruential generator
  263.  *
  264.  *  x_{k+1} = a x_k  (mod 2^46)
  265.  *
  266.  *  where 0 < x_k < 2^46 and 0 < a < 2^46.  This scheme generates 2^44 numbers
  267.  *  before repeating.  The argument A is the same as 'a' in the above formula,
  268.  *  and X is the same as x_0.  A and X must be odd double precision integers
  269.  *  in the range (1, 2^46).  The returned value RANDLC is normalized to be
  270.  *  between 0 and 1, i.e. RANDLC = 2^(-46) * x_1.  X is updated to contain
  271.  *  the new seed x_1, so that subsequent calls to RANDLC using the same
  272.  *  arguments will generate a continuous sequence.
  273.  *
  274.  *  This routine should produce the same results on any computer with at least
  275.  *  48 mantissa bits in double precision floating point data.  On Cray systems,
  276.  *  double precision should be disabled.
  277.  *
  278.  *  David H. Bailey     October 26, 1990
  279.  *
  280.  *     IMPLICIT DOUBLE PRECISION (A-H, O-Z)
  281.  *     SAVE KS, R23, R46, T23, T46
  282.  *     DATA KS/0/
  283.  *
  284.  *  If this is the first call to RANDLC, compute R23 = 2 ^ -23, R46 = 2 ^ -46,
  285.  *  T23 = 2 ^ 23, and T46 = 2 ^ 46.  These are computed in loops, rather than
  286.  *  by merely using the ** operator, in order to insure that the results are
  287.  *  exact on all systems.  This code assumes that 0.5D0 is represented exactly.
  288.  */
  289.  
  290. /*****************************************************************/
  291. /*************           R  A  N  D  L  C             ************/
  292. /*************                                        ************/
  293. /*************    portable random number generator    ************/
  294. /*****************************************************************/
  295.  
  296. static int      KS=0;
  297. static double   R23, R46, T23, T46;
  298. #pragma omp threadprivate(KS, R23, R46, T23, T46)
  299.  
  300. double  randlc( double *X, double *A )
  301. {
  302.       double        T1, T2, T3, T4;
  303.       double        A1;
  304.       double        A2;
  305.       double        X1;
  306.       double        X2;
  307.       double        Z;
  308.       int           i, j;
  309.  
  310.       if (KS == 0)
  311.       {
  312.         R23 = 1.0;
  313.         R46 = 1.0;
  314.         T23 = 1.0;
  315.         T46 = 1.0;
  316.    
  317.         for (i=1; i<=23; i++)
  318.         {
  319.           R23 = 0.50 * R23;
  320.           T23 = 2.0 * T23;
  321.         }
  322.         for (i=1; i<=46; i++)
  323.         {
  324.           R46 = 0.50 * R46;
  325.           T46 = 2.0 * T46;
  326.         }
  327.         KS = 1;
  328.       }
  329.  
  330. /*  Break A into two parts such that A = 2^23 * A1 + A2 and set X = N.  */
  331.  
  332.       T1 = R23 * *A;
  333.       j  = T1;
  334.       A1 = j;
  335.       A2 = *A - T23 * A1;
  336.  
  337. /*  Break X into two parts such that X = 2^23 * X1 + X2, compute
  338.     Z = A1 * X2 + A2 * X1  (mod 2^23), and then
  339.     X = 2^23 * Z + A2 * X2  (mod 2^46).                            */
  340.  
  341.       T1 = R23 * *X;
  342.       j  = T1;
  343.       X1 = j;
  344.       X2 = *X - T23 * X1;
  345.       T1 = A1 * X2 + A2 * X1;
  346.      
  347.       j  = R23 * T1;
  348.       T2 = j;
  349.       Z = T1 - T23 * T2;
  350.       T3 = T23 * Z + A2 * X2;
  351.       j  = R46 * T3;
  352.       T4 = j;
  353.       *X = T3 - T46 * T4;
  354.       return(R46 * *X);
  355. }
  356.  
  357.  
  358.  
  359.  
  360. /*****************************************************************/
  361. /************   F  I  N  D  _  M  Y  _  S  E  E  D    ************/
  362. /************                                         ************/
  363. /************ returns parallel random number seq seed ************/
  364. /*****************************************************************/
  365.  
  366. /*
  367.  * Create a random number sequence of total length nn residing
  368.  * on np number of processors.  Each processor will therefore have a
  369.  * subsequence of length nn/np.  This routine returns that random
  370.  * number which is the first random number for the subsequence belonging
  371.  * to processor rank kn, and which is used as seed for proc kn ran # gen.
  372.  */
  373.  
  374. double   find_my_seed( int kn,        /* my processor rank, 0<=kn<=num procs */
  375.                        int np,        /* np = num procs                      */
  376.                        long nn,       /* total num of ran numbers, all procs */
  377.                        double s,      /* Ran num seed, for ex.: 314159265.00 */
  378.                        double a )     /* Ran num gen mult, try 1220703125.00 */
  379. {
  380.  
  381.       double t1,t2;
  382.       long   mq,nq,kk,ik;
  383.  
  384.       if ( kn == 0 ) return s;
  385.  
  386.       mq = (nn/4 + np - 1) / np;
  387.       nq = mq * 4 * kn;               /* number of rans to be skipped */
  388.  
  389.       t1 = s;
  390.       t2 = a;
  391.       kk = nq;
  392.       while ( kk > 1 ) {
  393.          ik = kk / 2;
  394.          if( 2 * ik ==  kk ) {
  395.             (void)randlc( &t2, &t2 );
  396.         kk = ik;
  397.      }
  398.      else {
  399.             (void)randlc( &t1, &t2 );
  400.         kk = kk - 1;
  401.      }
  402.       }
  403.       (void)randlc( &t1, &t2 );
  404.  
  405.       return( t1 );
  406.  
  407. }
  408.  
  409.  
  410.  
  411. /*****************************************************************/
  412. /*************      C  R  E  A  T  E  _  S  E  Q      ************/
  413. /*****************************************************************/
  414.  
  415. void    create_seq( double seed, double a )
  416. {
  417.     double x, s;
  418.     INT_TYPE i, k;
  419.  
  420. #pragma omp parallel private(x,s,i,k)
  421.     {
  422.     INT_TYPE k1, k2;
  423.     double an = a;
  424.     int myid, num_procs;
  425.         INT_TYPE mq;
  426.  
  427. #ifdef _OPENMP
  428.     myid = omp_get_thread_num();
  429.     num_procs = omp_get_num_threads();
  430. #else
  431.     myid = 0;
  432.     num_procs = 1;
  433. #endif
  434.  
  435.     mq = (NUM_KEYS + num_procs - 1) / num_procs;
  436.     k1 = mq * myid;
  437.     k2 = k1 + mq;
  438.     if ( k2 > NUM_KEYS ) k2 = NUM_KEYS;
  439.  
  440.     KS = 0;
  441.     s = find_my_seed( myid, num_procs,
  442.               (long)4*NUM_KEYS, seed, an );
  443.  
  444.         k = MAX_KEY/4;
  445.  
  446.     for (i=k1; i<k2; i++)
  447.     {
  448.         x = randlc(&s, &an);
  449.         x += randlc(&s, &an);
  450.             x += randlc(&s, &an);
  451.         x += randlc(&s, &an);  
  452.  
  453.             key_array[i] = k*x;
  454.     }
  455.     } /*omp parallel*/
  456. }
  457.  
  458.  
  459.  
  460. /*****************************************************************/
  461. /*****************    Allocate Working Buffer     ****************/
  462. /*****************************************************************/
  463. void *alloc_mem( size_t size )
  464. {
  465.     void *p;
  466.  
  467.     p = (void *)malloc(size);
  468.     if (!p) {
  469.         perror("Memory allocation error");
  470.         exit(1);
  471.     }
  472.     return p;
  473. }
  474.  
  475. void alloc_key_buff( void )
  476. {
  477.     INT_TYPE i;
  478.     int      num_procs;
  479.  
  480.  
  481. #ifdef _OPENMP
  482.     num_procs = omp_get_max_threads();
  483. #else
  484.     num_procs = 1;
  485. #endif
  486.  
  487. #ifdef USE_BUCKETS
  488.     bucket_size = (INT_TYPE **)alloc_mem(sizeof(INT_TYPE *) * num_procs);
  489.  
  490.     for (i = 0; i < num_procs; i++) {
  491.         bucket_size[i] = (INT_TYPE *)alloc_mem(sizeof(INT_TYPE) * NUM_BUCKETS);
  492.     }
  493.  
  494.     #pragma omp parallel for
  495.     for( i=0; i<NUM_KEYS; i++ )
  496.         key_buff2[i] = 0;
  497.  
  498. #else /*USE_BUCKETS*/
  499.  
  500.     key_buff1_aptr = (INT_TYPE **)alloc_mem(sizeof(INT_TYPE *) * num_procs);
  501.  
  502.     key_buff1_aptr[0] = key_buff1;
  503.     for (i = 1; i < num_procs; i++) {
  504.         key_buff1_aptr[i] = (INT_TYPE *)alloc_mem(sizeof(INT_TYPE) * MAX_KEY);
  505.     }
  506.  
  507. #endif /*USE_BUCKETS*/
  508. }
  509.  
  510.  
  511.  
  512. /*****************************************************************/
  513. /*************    F  U  L  L  _  V  E  R  I  F  Y     ************/
  514. /*****************************************************************/
  515.  
  516.  
  517. void full_verify( void )
  518. {
  519.     INT_TYPE   i, j;
  520.     INT_TYPE   k, k1, k2;
  521.  
  522.  
  523. /*  Now, finally, sort the keys:  */
  524.  
  525. /*  Copy keys into work array; keys in key_array will be reassigned. */
  526.  
  527. #ifdef USE_BUCKETS
  528.  
  529.     /* Buckets are already sorted.  Sorting keys within each bucket */
  530. #ifdef SCHED_CYCLIC
  531.     #pragma omp parallel for private(i,j,k,k1) schedule(static,1)
  532. #else
  533.     #pragma omp parallel for private(i,j,k,k1) schedule(dynamic)
  534. #endif
  535.     for( j=0; j< NUM_BUCKETS; j++ ) {
  536.  
  537.         k1 = (j > 0)? bucket_ptrs[j-1] : 0;
  538.         for ( i = k1; i < bucket_ptrs[j]; i++ ) {
  539.             k = --key_buff_ptr_global[key_buff2[i]];
  540.             key_array[k] = key_buff2[i];
  541.         }
  542.     }
  543.  
  544. #else
  545.  
  546. #pragma omp parallel private(i,j,k,k1,k2)
  547.   {
  548.     #pragma omp for
  549.     for( i=0; i<NUM_KEYS; i++ )
  550.         key_buff2[i] = key_array[i];
  551.  
  552.     /* This is actual sorting. Each thread is responsible for
  553.        a subset of key values */
  554.     j = omp_get_num_threads();
  555.     j = (MAX_KEY + j - 1) / j;
  556.     k1 = j * omp_get_thread_num();
  557.     k2 = k1 + j;
  558.     if (k2 > MAX_KEY) k2 = MAX_KEY;
  559.  
  560.     for( i=0; i<NUM_KEYS; i++ ) {
  561.         if (key_buff2[i] >= k1 && key_buff2[i] < k2) {
  562.             k = --key_buff_ptr_global[key_buff2[i]];
  563.             key_array[k] = key_buff2[i];
  564.         }
  565.     }
  566.   } /*omp parallel*/
  567.  
  568. #endif
  569.  
  570.  
  571. /*  Confirm keys correctly sorted: count incorrectly sorted keys, if any */
  572.  
  573.     j = 0;
  574.     #pragma omp parallel for reduction(+:j)
  575.     for( i=1; i<NUM_KEYS; i++ )
  576.         if( key_array[i-1] > key_array[i] )
  577.             j++;
  578.  
  579.     if( j != 0 )
  580.         printf( "Full_verify: number of keys out of sort: %ld\n", (long)j );
  581.     else
  582.         passed_verification++;
  583.  
  584. }
  585.  
  586.  
  587.  
  588.  
  589. /*****************************************************************/
  590. /*************             R  A  N  K             ****************/
  591. /*****************************************************************/
  592.  
  593.  
  594. void rank( int iteration )
  595. {
  596.  
  597.     INT_TYPE    i, k;
  598.     INT_TYPE    *key_buff_ptr, *key_buff_ptr2;
  599.  
  600. #ifdef USE_BUCKETS
  601.     int shift = MAX_KEY_LOG_2 - NUM_BUCKETS_LOG_2;
  602.     INT_TYPE num_bucket_keys = (1L << shift);
  603. #endif
  604.  
  605.  
  606.     key_array[iteration] = iteration;
  607.     key_array[iteration+MAX_ITERATIONS] = MAX_KEY - iteration;
  608.  
  609.  
  610. /*  Determine where the partial verify test keys are, load into  */
  611. /*  top of array bucket_size                                     */
  612.     for( i=0; i<TEST_ARRAY_SIZE; i++ )
  613.         partial_verify_vals[i] = key_array[test_index_array[i]];
  614.  
  615.  
  616. /*  Setup pointers to key buffers  */
  617. #ifdef USE_BUCKETS
  618.     key_buff_ptr2 = key_buff2;
  619. #else
  620.     key_buff_ptr2 = key_array;
  621. #endif
  622.     key_buff_ptr = key_buff1;
  623.  
  624.  
  625. #pragma omp parallel private(i, k)
  626.   {
  627.     INT_TYPE *work_buff, m, k1, k2;
  628.     int myid = 0, num_procs = 1;
  629.  
  630. #ifdef _OPENMP
  631.     myid = omp_get_thread_num();
  632.     num_procs = omp_get_num_threads();
  633. #endif
  634.  
  635.  
  636. /*  Bucket sort is known to improve cache performance on some   */
  637. /*  cache based systems.  But the actual performance may depend */
  638. /*  on cache size, problem size. */
  639. #ifdef USE_BUCKETS
  640.  
  641.     work_buff = bucket_size[myid];
  642.  
  643. /*  Initialize */
  644.     for( i=0; i<NUM_BUCKETS; i++ )  
  645.         work_buff[i] = 0;
  646.  
  647. /*  Determine the number of keys in each bucket */
  648.     #pragma omp for schedule(static)
  649.     for( i=0; i<NUM_KEYS; i++ )
  650.         work_buff[key_array[i] >> shift]++;
  651.  
  652. /*  Accumulative bucket sizes are the bucket pointers.
  653.     These are global sizes accumulated upon to each bucket */
  654.     bucket_ptrs[0] = 0;
  655.     for( k=0; k< myid; k++ )  
  656.         bucket_ptrs[0] += bucket_size[k][0];
  657.  
  658.     for( i=1; i< NUM_BUCKETS; i++ ) {
  659.         bucket_ptrs[i] = bucket_ptrs[i-1];
  660.         for( k=0; k< myid; k++ )
  661.             bucket_ptrs[i] += bucket_size[k][i];
  662.         for( k=myid; k< num_procs; k++ )
  663.             bucket_ptrs[i] += bucket_size[k][i-1];
  664.     }
  665.  
  666.  
  667. /*  Sort into appropriate bucket */
  668.     #pragma omp for schedule(static)
  669.     for( i=0; i<NUM_KEYS; i++ )  
  670.     {
  671.         k = key_array[i];
  672.         key_buff2[bucket_ptrs[k >> shift]++] = k;
  673.     }
  674.  
  675. /*  The bucket pointers now point to the final accumulated sizes */
  676.     if (myid < num_procs-1) {
  677.         for( i=0; i< NUM_BUCKETS; i++ )
  678.             for( k=myid+1; k< num_procs; k++ )
  679.                 bucket_ptrs[i] += bucket_size[k][i];
  680.     }
  681.  
  682.  
  683. /*  Now, buckets are sorted.  We only need to sort keys inside
  684.     each bucket, which can be done in parallel.  Because the distribution
  685.     of the number of keys in the buckets is Gaussian, the use of
  686.     a dynamic schedule should improve load balance, thus, performance     */
  687.  
  688. #ifdef SCHED_CYCLIC
  689.     #pragma omp for schedule(static,1)
  690. #else
  691.     #pragma omp for schedule(dynamic)
  692. #endif
  693.     for( i=0; i< NUM_BUCKETS; i++ ) {
  694.  
  695. /*  Clear the work array section associated with each bucket */
  696.         k1 = i * num_bucket_keys;
  697.         k2 = k1 + num_bucket_keys;
  698.         for ( k = k1; k < k2; k++ )
  699.             key_buff_ptr[k] = 0;
  700.  
  701. /*  Ranking of all keys occurs in this section:                 */
  702.  
  703. /*  In this section, the keys themselves are used as their
  704.     own indexes to determine how many of each there are: their
  705.     individual population                                       */
  706.         m = (i > 0)? bucket_ptrs[i-1] : 0;
  707.         for ( k = m; k < bucket_ptrs[i]; k++ )
  708.             key_buff_ptr[key_buff_ptr2[k]]++;  /* Now they have individual key   */
  709.                                        /* population                     */
  710.  
  711. /*  To obtain ranks of each key, successively add the individual key
  712.     population, not forgetting to add m, the total of lesser keys,
  713.     to the first key population                                          */
  714.         key_buff_ptr[k1] += m;
  715.         for ( k = k1+1; k < k2; k++ )
  716.             key_buff_ptr[k] += key_buff_ptr[k-1];
  717.  
  718.     }
  719.  
  720. #else /*USE_BUCKETS*/
  721.  
  722.  
  723.     work_buff = key_buff1_aptr[myid];
  724.  
  725.  
  726. /*  Clear the work array */
  727.     for( i=0; i<MAX_KEY; i++ )
  728.         work_buff[i] = 0;
  729.  
  730.  
  731. /*  Ranking of all keys occurs in this section:                 */
  732.  
  733. /*  In this section, the keys themselves are used as their
  734.     own indexes to determine how many of each there are: their
  735.     individual population                                       */
  736.  
  737.     #pragma omp for nowait schedule(static)
  738.     for( i=0; i<NUM_KEYS; i++ )
  739.         work_buff[key_buff_ptr2[i]]++;  /* Now they have individual key   */
  740.                                        /* population                     */
  741.  
  742. /*  To obtain ranks of each key, successively add the individual key
  743.     population                                          */
  744.  
  745.     for( i=0; i<MAX_KEY-1; i++ )  
  746.         work_buff[i+1] += work_buff[i];
  747.  
  748.     #pragma omp barrier
  749.  
  750. /*  Accumulate the global key population */
  751.     for( k=1; k<num_procs; k++ ) {
  752.         #pragma omp for nowait schedule(static)
  753.         for( i=0; i<MAX_KEY; i++ )
  754.             key_buff_ptr[i] += key_buff1_aptr[k][i];
  755.     }
  756.  
  757. #endif /*USE_BUCKETS*/
  758.  
  759.   } /*omp parallel*/
  760.  
  761. /* This is the partial verify test section */
  762. /* Observe that test_rank_array vals are   */
  763. /* shifted differently for different cases */
  764.     for( i=0; i<TEST_ARRAY_SIZE; i++ )
  765.     {                                            
  766.         k = partial_verify_vals[i];          /* test vals were put here */
  767.         if( 0 < k  &&  k <= NUM_KEYS-1 )
  768.         {
  769.             INT_TYPE key_rank = key_buff_ptr[k-1];
  770.             int failed = 0;
  771.  
  772.             switch( CLASS )
  773.             {
  774.                 case 'S':
  775.                     if( i <= 2 )
  776.                     {
  777.                         if( key_rank != test_rank_array[i]+iteration )
  778.                             failed = 1;
  779.                         else
  780.                             passed_verification++;
  781.                     }
  782.                     else
  783.                     {
  784.                         if( key_rank != test_rank_array[i]-iteration )
  785.                             failed = 1;
  786.                         else
  787.                             passed_verification++;
  788.                     }
  789.                     break;
  790.                 case 'W':
  791.                     if( i < 2 )
  792.                     {
  793.                         if( key_rank != test_rank_array[i]+(iteration-2) )
  794.                             failed = 1;
  795.                         else
  796.                             passed_verification++;
  797.                     }
  798.                     else
  799.                     {
  800.                         if( key_rank != test_rank_array[i]-iteration )
  801.                             failed = 1;
  802.                         else
  803.                             passed_verification++;
  804.                     }
  805.                     break;
  806.                 case 'A':
  807.                     if( i <= 2 )
  808.                 {
  809.                         if( key_rank != test_rank_array[i]+(iteration-1) )
  810.                             failed = 1;
  811.                         else
  812.                             passed_verification++;
  813.                 }
  814.                     else
  815.                     {
  816.                         if( key_rank != test_rank_array[i]-(iteration-1) )
  817.                             failed = 1;
  818.                         else
  819.                             passed_verification++;
  820.                     }
  821.                     break;
  822.                 case 'B':
  823.                     if( i == 1 || i == 2 || i == 4 )
  824.                 {
  825.                         if( key_rank != test_rank_array[i]+iteration )
  826.                             failed = 1;
  827.                         else
  828.                             passed_verification++;
  829.                 }
  830.                     else
  831.                     {
  832.                         if( key_rank != test_rank_array[i]-iteration )
  833.                             failed = 1;
  834.                         else
  835.                             passed_verification++;
  836.                     }
  837.                     break;
  838.                 case 'C':
  839.                     if( i <= 2 )
  840.                 {
  841.                         if( key_rank != test_rank_array[i]+iteration )
  842.                             failed = 1;
  843.                         else
  844.                             passed_verification++;
  845.                 }
  846.                     else
  847.                     {
  848.                         if( key_rank != test_rank_array[i]-iteration )
  849.                             failed = 1;
  850.                         else
  851.                             passed_verification++;
  852.                     }
  853.                     break;
  854.                 case 'D':
  855.                     if( i < 2 )
  856.                 {
  857.                         if( key_rank != test_rank_array[i]+iteration )
  858.                             failed = 1;
  859.                         else
  860.                             passed_verification++;
  861.                 }
  862.                     else
  863.                     {
  864.                         if( key_rank != test_rank_array[i]-iteration )
  865.                             failed = 1;
  866.                         else
  867.                             passed_verification++;
  868.                     }
  869.                     break;
  870.             }
  871.             if( failed == 1 )
  872.                 printf( "Failed partial verification: "
  873.                         "iteration %d, test key %d\n",
  874.                          iteration, (int)i );
  875.         }
  876.     }
  877.  
  878.  
  879.  
  880.  
  881. /*  Make copies of rank info for use by full_verify: these variables
  882.     in rank are local; making them global slows down the code, probably
  883.     since they cannot be made register by compiler                        */
  884.  
  885.     if( iteration == MAX_ITERATIONS )
  886.         key_buff_ptr_global = key_buff_ptr;
  887.  
  888. }      
  889.  
  890.  
  891. /*****************************************************************/
  892. /*************             M  A  I  N             ****************/
  893. /*****************************************************************/
  894.  
  895. int main( int argc, char **argv )
  896. {
  897.  
  898.     int             i, iteration, timer_on;
  899.  
  900.     double          timecounter;
  901.  
  902.     FILE            *fp;
  903.  
  904.  
  905. /*  Initialize timers  */
  906.     timer_on = 0;            
  907.     if ((fp = fopen("timer.flag", "r")) != NULL) {
  908.         fclose(fp);
  909.         timer_on = 1;
  910.     }
  911.     timer_clear( 0 );
  912.     if (timer_on) {
  913.         timer_clear( 1 );
  914.         timer_clear( 2 );
  915.         timer_clear( 3 );
  916.     }
  917.  
  918.     if (timer_on) timer_start( 3 );
  919.  
  920.  
  921. /*  Initialize the verification arrays if a valid class */
  922.     for( i=0; i<TEST_ARRAY_SIZE; i++ )
  923.         switch( CLASS )
  924.         {
  925.             case 'S':
  926.                 test_index_array[i] = S_test_index_array[i];
  927.                 test_rank_array[i]  = S_test_rank_array[i];
  928.                 break;
  929.             case 'A':
  930.                 test_index_array[i] = A_test_index_array[i];
  931.                 test_rank_array[i]  = A_test_rank_array[i];
  932.                 break;
  933.             case 'W':
  934.                 test_index_array[i] = W_test_index_array[i];
  935.                 test_rank_array[i]  = W_test_rank_array[i];
  936.                 break;
  937.             case 'B':
  938.                 test_index_array[i] = B_test_index_array[i];
  939.                 test_rank_array[i]  = B_test_rank_array[i];
  940.                 break;
  941.             case 'C':
  942.                 test_index_array[i] = C_test_index_array[i];
  943.                 test_rank_array[i]  = C_test_rank_array[i];
  944.                 break;
  945.             case 'D':
  946.                 test_index_array[i] = D_test_index_array[i];
  947.                 test_rank_array[i]  = D_test_rank_array[i];
  948.                 break;
  949.         };
  950.  
  951.        
  952.  
  953. /*  Printout initial NPB info */
  954.     printf
  955.       ( "\n\n NAS Parallel Benchmarks (NPB3.3-OMP) - IS Benchmark\n\n" );
  956.     printf( " Size:  %ld  (class %c)\n", (long)TOTAL_KEYS, CLASS );
  957.     printf( " Iterations:  %d\n", MAX_ITERATIONS );
  958. #ifdef _OPENMP
  959.     printf( " Number of available threads:  %d\n", omp_get_max_threads() );
  960. #endif
  961.     printf( "\n" );
  962.  
  963.     if (timer_on) timer_start( 1 );
  964.  
  965. /*  Generate random number sequence and subsequent keys on all procs */
  966.     create_seq( 314159265.00,                    /* Random number gen seed */
  967.                 1220703125.00 );                 /* Random number gen mult */
  968.  
  969.     alloc_key_buff();
  970.     if (timer_on) timer_stop( 1 );
  971.  
  972.  
  973. /*  Do one interation for free (i.e., untimed) to guarantee initialization of  
  974.     all data and code pages and respective tables */
  975.     rank( 1 );  
  976.  
  977. /*  Start verification counter */
  978.     passed_verification = 0;
  979.  
  980.     if( CLASS != 'S' ) printf( "\n   iteration\n" );
  981.  
  982. /*  Start timer  */            
  983.     timer_start( 0 );
  984.  
  985.  
  986. /*  This is the main iteration */
  987.     for( iteration=1; iteration<=MAX_ITERATIONS; iteration++ )
  988.     {
  989.         if( CLASS != 'S' ) printf( "        %d\n", iteration );
  990.         rank( iteration );
  991.     }
  992.  
  993.  
  994. /*  End of timing, obtain maximum time of all processors */
  995.     timer_stop( 0 );
  996.     timecounter = timer_read( 0 );
  997.  
  998.  
  999. /*  This tests that keys are in sequence: sorting of last ranked key seq
  1000.     occurs here, but is an untimed operation                             */
  1001.     if (timer_on) timer_start( 2 );
  1002.     full_verify();
  1003.     if (timer_on) timer_stop( 2 );
  1004.  
  1005.     if (timer_on) timer_stop( 3 );
  1006.  
  1007.  
  1008. /*  The final printout  */
  1009.     if( passed_verification != 5*MAX_ITERATIONS + 1 )
  1010.         passed_verification = 0;
  1011.     c_print_results( "IS",
  1012.                      CLASS,
  1013.                      (int)(TOTAL_KEYS/64),
  1014.                      64,
  1015.                      0,
  1016.                      MAX_ITERATIONS,
  1017.                      timecounter,
  1018.                      ((double) (MAX_ITERATIONS*TOTAL_KEYS))
  1019.                                                   /timecounter/1000000.,
  1020.                      "keys ranked",
  1021.                      passed_verification,
  1022.                      NPBVERSION,
  1023.                      COMPILETIME,
  1024.                      CC,
  1025.                      CLINK,
  1026.                      C_LIB,
  1027.                      C_INC,
  1028.                      CFLAGS,
  1029.                      CLINKFLAGS );
  1030.  
  1031.  
  1032. /*  Print additional timers  */
  1033.     if (timer_on) {
  1034.        double t_total, t_percent;
  1035.  
  1036.        t_total = timer_read( 3 );
  1037.        printf("\nAdditional timers -\n");
  1038.        printf(" Total execution: %8.3f\n", t_total);
  1039.        if (t_total == 0.0) t_total = 1.0;
  1040.        timecounter = timer_read(1);
  1041.        t_percent = timecounter/t_total * 100.;
  1042.        printf(" Initialization : %8.3f (%5.2f%%)\n", timecounter, t_percent);
  1043.        timecounter = timer_read(0);
  1044.        t_percent = timecounter/t_total * 100.;
  1045.        printf(" Benchmarking   : %8.3f (%5.2f%%)\n", timecounter, t_percent);
  1046.        timecounter = timer_read(2);
  1047.        t_percent = timecounter/t_total * 100.;
  1048.        printf(" Sorting        : %8.3f (%5.2f%%)\n", timecounter, t_percent);
  1049.     }
  1050.  
  1051.     return 0;
  1052.          /**************************/
  1053. }        /*  E N D  P R O G R A M  */
  1054.          /**************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement