kmp_sched.cpp

Go to the documentation of this file.
00001 /*
00002  * kmp_sched.c -- static scheduling -- iteration initialization
00003  * $Revision: 42178 $
00004  * $Date: 2013-03-22 07:07:59 -0500 (Fri, 22 Mar 2013) $
00005  */
00006 
00007 /* <copyright>
00008     Copyright (c) 1997-2013 Intel Corporation.  All Rights Reserved.
00009 
00010     Redistribution and use in source and binary forms, with or without
00011     modification, are permitted provided that the following conditions
00012     are met:
00013 
00014       * Redistributions of source code must retain the above copyright
00015         notice, this list of conditions and the following disclaimer.
00016       * Redistributions in binary form must reproduce the above copyright
00017         notice, this list of conditions and the following disclaimer in the
00018         documentation and/or other materials provided with the distribution.
00019       * Neither the name of Intel Corporation nor the names of its
00020         contributors may be used to endorse or promote products derived
00021         from this software without specific prior written permission.
00022 
00023     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 
00035 
00036 ------------------------------------------------------------------------
00037 
00038     Portions of this software are protected under the following patents:
00039         U.S. Patent 5,812,852
00040         U.S. Patent 6,792,599
00041         U.S. Patent 7,069,556
00042         U.S. Patent 7,328,433
00043         U.S. Patent 7,500,242
00044 
00045 </copyright> */
00046 
00047 /*
00048  * Dynamic scheduling initialization and dispatch.
00049  *
00050  * NOTE: team->t.t_nproc is a constant inside of any dispatch loop, however
00051  *       it may change values between parallel regions.  __kmp_max_nth
00052  *       is the largest value __kmp_nth may take, 1 is the smallest.
00053  *
00054  */
00055 
00056 #include "kmp.h"
00057 #include "kmp_i18n.h"
00058 #include "kmp_str.h"
00059 #include "kmp_error.h"
00060 
00061 // template for type limits
00062 template< typename T >
00063 struct i_maxmin {
00064     static const T mx;
00065     static const T mn;
00066 };
00067 template<>
00068 struct i_maxmin< int > {
00069     static const int mx = 0x7fffffff;
00070     static const int mn = 0x80000000;
00071 };
00072 template<>
00073 struct i_maxmin< unsigned int > {
00074     static const unsigned int mx = 0xffffffff;
00075     static const unsigned int mn = 0x00000000;
00076 };
00077 template<>
00078 struct i_maxmin< long long > {
00079     static const long long mx = 0x7fffffffffffffffLL;
00080     static const long long mn = 0x8000000000000000LL;
00081 };
00082 template<>
00083 struct i_maxmin< unsigned long long > {
00084     static const unsigned long long mx = 0xffffffffffffffffLL;
00085     static const unsigned long long mn = 0x0000000000000000LL;
00086 };
00087 //-------------------------------------------------------------------------
00088 #ifdef KMP_DEBUG
00089 //-------------------------------------------------------------------------
00090 // template for debug prints specification ( d, u, lld, llu )
00091     char const * traits_t< int >::spec = "d";
00092     char const * traits_t< unsigned int >::spec = "u";
00093     char const * traits_t< long long >::spec = "lld";
00094     char const * traits_t< unsigned long long >::spec = "llu";
00095 //-------------------------------------------------------------------------
00096 #endif
00097 
00098 template< typename T >
00099 static void
00100 __kmp_for_static_init(
00101     ident_t                          *loc,
00102     kmp_int32                         global_tid,
00103     kmp_int32                         schedtype,
00104     kmp_int32                        *plastiter,
00105     T                                *plower,
00106     T                                *pupper,
00107     typename traits_t< T >::signed_t *pstride,
00108     typename traits_t< T >::signed_t  incr,
00109     typename traits_t< T >::signed_t  chunk
00110 ) {
00111     typedef typename traits_t< T >::unsigned_t  UT;
00112     typedef typename traits_t< T >::signed_t    ST;
00113     /*  this all has to be changed back to TID and such.. */
00114     register kmp_int32   gtid = global_tid;
00115     register kmp_uint32  tid  = __kmp_tid_from_gtid( global_tid );
00116     register kmp_uint32  nth;
00117     register UT          trip_count;
00118     register kmp_team_t *team = __kmp_threads[ gtid ]->th.th_team;
00119 
00120     KE_TRACE( 10, ("__kmpc_for_static_init called (%d)\n", global_tid));
00121     #ifdef KMP_DEBUG
00122     {
00123         const char * buff;
00124         // create format specifiers before the debug output
00125         buff = __kmp_str_format(
00126             "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s," \
00127             " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
00128             traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
00129             traits_t< ST >::spec, traits_t< ST >::spec, traits_t< T >::spec );
00130         KD_TRACE(100, ( buff, global_tid, schedtype, *plastiter,
00131             *plower, *pupper, *pstride, incr, chunk ) );
00132         __kmp_str_free( &buff );
00133     }
00134     #endif
00135 
00136     if ( __kmp_env_consistency_check ) {
00137         __kmp_push_workshare( global_tid, ct_pdo, loc );
00138         if ( incr == 0 ) {
00139             __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo, loc );
00140 
00141         }
00142     }
00143     /* special handling for zero-trip loops */
00144     if ( incr > 0 ? (*pupper < *plower) : (*plower < *pupper) ) {
00145         *plastiter = FALSE;
00146         /* leave pupper and plower set to entire iteration space */
00147         *pstride = incr;   /* value should never be used */
00148     //        *plower = *pupper - incr;   // let compiler bypass the illegal loop (like for(i=1;i<10;i--))  THIS LINE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE ON A ZERO-TRIP LOOP (lower=1,\
00149       upper=0,stride=1) - JPH June 23, 2009.
00150         #ifdef KMP_DEBUG
00151         {
00152             const char * buff;
00153             // create format specifiers before the debug output
00154             buff = __kmp_str_format(
00155                 "__kmpc_for_static_init:(ZERO TRIP) liter=%%d lower=%%%s upper=%%%s stride = %%%s signed?<%s>, loc = %%s\n",
00156                 traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec, traits_t< T >::spec );
00157             KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride, loc->psource ) );
00158             __kmp_str_free( &buff );
00159         }
00160         #endif
00161         KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );
00162         return;
00163     }
00164 
00165     /* determine if "for" loop is an active worksharing construct */
00166     if ( team -> t.t_serialized ) {
00167         /* serialized parallel, each thread executes whole iteration space */
00168         *plastiter = TRUE;
00169         /* leave pupper and plower set to entire iteration space */
00170         *pstride = (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
00171 
00172         #ifdef KMP_DEBUG
00173         {
00174             const char * buff;
00175             // create format specifiers before the debug output
00176             buff = __kmp_str_format(
00177                 "__kmpc_for_static_init: (serial) liter=%%d lower=%%%s upper=%%%s stride = %%%s\n",
00178                 traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec );
00179             KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
00180             __kmp_str_free( &buff );
00181         }
00182         #endif
00183         KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );
00184         return;
00185     }
00186     nth = team->t.t_nproc;
00187     if ( nth == 1 ) {
00188         *plastiter = TRUE;
00189 
00190         #ifdef KMP_DEBUG
00191         {
00192             const char * buff;
00193             // create format specifiers before the debug output
00194             buff = __kmp_str_format(
00195                 "__kmpc_for_static_init: (serial) liter=%%d lower=%%%s upper=%%%s stride = %%%s\n",
00196                 traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec );
00197             KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
00198             __kmp_str_free( &buff );
00199         }
00200         #endif
00201         KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );
00202         return;
00203     }
00204 
00205     /* compute trip count */
00206     if ( incr == 1 ) {
00207         trip_count = *pupper - *plower + 1;
00208     } else if (incr == -1) {
00209         trip_count = *plower - *pupper + 1;
00210     } else {
00211         if ( incr > 1 ) {
00212             trip_count = (*pupper - *plower) / incr + 1;
00213         } else {
00214             trip_count = (*plower - *pupper) / ( -incr ) + 1;
00215         }
00216     }
00217     if ( __kmp_env_consistency_check ) {
00218         /* tripcount overflow? */
00219         if ( trip_count == 0 && *pupper != *plower ) {
00220             __kmp_error_construct( kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo, loc );
00221         }
00222     }
00223 
00224     /* compute remaining parameters */
00225     switch ( schedtype ) {
00226     case kmp_sch_static:
00227         {
00228             if ( trip_count < nth ) {
00229                 KMP_DEBUG_ASSERT(
00230                     __kmp_static == kmp_sch_static_greedy || \
00231                     __kmp_static == kmp_sch_static_balanced
00232                 ); // Unknown static scheduling type.
00233                 if ( tid < trip_count ) {
00234                     *pupper = *plower = *plower + tid * incr;
00235                 } else {
00236                     *plower = *pupper + incr;
00237                 }
00238                 *plastiter = ( tid == trip_count - 1 );
00239             } else {
00240                 if ( __kmp_static == kmp_sch_static_balanced ) {
00241                     register UT small_chunk = trip_count / nth;
00242                     register UT extras = trip_count % nth;
00243                     *plower += incr * ( tid * small_chunk + ( tid < extras ? tid : extras ) );
00244                     *pupper = *plower + small_chunk * incr - ( tid < extras ? 0 : incr );
00245                     *plastiter = ( tid == nth - 1 );
00246                 } else {
00247                     register T big_chunk_inc_count = ( trip_count/nth +
00248                                                      ( ( trip_count % nth ) ? 1 : 0) ) * incr;
00249                     register T old_upper = *pupper;
00250 
00251                     KMP_DEBUG_ASSERT( __kmp_static == kmp_sch_static_greedy );
00252                         // Unknown static scheduling type.
00253 
00254                     *plower += tid * big_chunk_inc_count;
00255                     *pupper = *plower + big_chunk_inc_count - incr;
00256                     if ( incr > 0 ) {
00257                         if ( *pupper < *plower ) {
00258                             *pupper = i_maxmin< T >::mx;
00259                         }
00260                         *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
00261                         if ( *pupper > old_upper ) *pupper = old_upper; // tracker C73258
00262                     } else {
00263                         if ( *pupper > *plower ) {
00264                             *pupper = i_maxmin< T >::mn;
00265                         }
00266                         *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
00267                         if ( *pupper < old_upper ) *pupper = old_upper; // tracker C73258
00268                     }
00269                 }
00270             }
00271             break;
00272         }
00273     case kmp_sch_static_chunked:
00274         {
00275             register T span;
00276             if ( chunk < 1 ) {
00277                 chunk = 1;
00278             }
00279             span = chunk * incr;
00280             *pstride = span * nth;
00281             *plower = *plower + (span * tid);
00282             *pupper = *plower + span - incr;
00283             /* TODO: is the following line a bug?  Shouldn't it be plastiter instead of *plastiter ? */
00284             if (*plastiter) { /* only calculate this if it was requested */
00285                 kmp_int32 lasttid = ((trip_count - 1) / ( UT )chunk) % nth;
00286                 *plastiter = (tid == lasttid);
00287             }
00288             break;
00289         }
00290     default:
00291         KMP_ASSERT2( 0, "__kmpc_for_static_init: unknown scheduling type" );
00292         break;
00293     }
00294 
00295     #ifdef KMP_DEBUG
00296     {
00297         const char * buff;
00298         // create format specifiers before the debug output
00299         buff = __kmp_str_format(
00300             "__kmpc_for_static_init: liter=%%d lower=%%%s upper=%%%s stride = %%%s signed?<%s>\n",
00301             traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec, traits_t< T >::spec );
00302         KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
00303         __kmp_str_free( &buff );
00304     }
00305     #endif
00306     KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );
00307 
00308 #if OMPT_SUPPORT
00309     kmp_info_t  *this_thr        = __kmp_threads[ global_tid ];
00310     if ((ompt_status == ompt_status_track_callback)) {
00311       if (ompt_callbacks.ompt_callback(ompt_event_loop_begin)) {
00312         ompt_callbacks.ompt_callback(ompt_event_loop_begin)
00313       (team->t.ompt_team_info.parallel_id,
00314        team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_id);
00315       }
00316     }
00317 #endif
00318 
00319     return;
00320 }
00321 
00322 //--------------------------------------------------------------------------------------
00323 extern "C" {
00324 
00345 void
00346 __kmpc_for_static_init_4( ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter,
00347                       kmp_int32 *plower, kmp_int32 *pupper,
00348                       kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk )
00349 {
00350     __kmp_for_static_init< kmp_int32 >(
00351                       loc, gtid, schedtype, plastiter, plower, pupper, pstride, incr, chunk );
00352 }
00353 
00357 void
00358 __kmpc_for_static_init_4u( ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter,
00359                       kmp_uint32 *plower, kmp_uint32 *pupper,
00360                       kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk )
00361 {
00362     __kmp_for_static_init< kmp_uint32 >(
00363                       loc, gtid, schedtype, plastiter, plower, pupper, pstride, incr, chunk );
00364 }
00365 
00369 void
00370 __kmpc_for_static_init_8( ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter,
00371                       kmp_int64 *plower, kmp_int64 *pupper,
00372                       kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk )
00373 {
00374     __kmp_for_static_init< kmp_int64 >(
00375                       loc, gtid, schedtype, plastiter, plower, pupper, pstride, incr, chunk );
00376 }
00377 
00381 void
00382 __kmpc_for_static_init_8u( ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter,
00383                       kmp_uint64 *plower, kmp_uint64 *pupper,
00384                       kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk )
00385 {
00386     __kmp_for_static_init< kmp_uint64 >(
00387                       loc, gtid, schedtype, plastiter, plower, pupper, pstride, incr, chunk );
00388 }
00393 } // extern "C"
00394 

Generated on 25 Aug 2013 for libomp_oss by  doxygen 1.6.1