Offer API for setting number of loop dispatch buffers

The problem is the lack of dispatch buffers when thousands of loops with nowait,
about 10 iterations each, are executed by hundreds of threads. We only have
built-in 7 dispatch buffers, but there is a need in dozens or hundreds of
buffers.

The problem can be fixed by setting KMP_MAX_DISP_BUF to bigger value. In order
to give users same possibility I changed build-time control into run-time one,
adding API just in case.

This change adds an environment variable KMP_DISP_NUM_BUFFERS and a new API
function kmp_set_disp_num_buffers(int num_buffers).

The KMP_DISP_NUM_BUFFERS envirable works only before serial initialization,
because during the serial initialization we already allocate buffers for the hot
team, so it is too late to change the number of buffers later (or we need to
reallocate buffers for all teams which sounds too complicated). The
kmp_set_defaults() routine does not work for this envirable, because it calls
serial initialization before reading the parameter string. So a new routine,
kmp_set_disp_num_buffers(), is created so that it can set our internal global
variable before the library initialization. If both the envirable and API used
the envirable wins.

Differential Revision: http://reviews.llvm.org/D20697


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@271318 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jonathan Peyton
2016-05-31 19:01:15 +00:00
parent cbb2a49897
commit ce32bac98c
16 changed files with 246 additions and 14 deletions
+3
View File
@@ -397,6 +397,7 @@ kmpc_set_defaults 224
%endif
%endif
kmpc_aligned_malloc 265
kmpc_set_disp_num_buffers 267
# User API entry points that have both lower- and upper- case versions for Fortran.
# Number for lowercase version is indicated. Number for uppercase is obtained by adding 1000.
@@ -528,6 +529,8 @@ kmp_set_warnings_off 780
%endif
%endif # OMP_41
kmp_set_disp_num_buffers 890
%ifndef stub
# Ordinals between 900 and 999 are reserved
+1
View File
@@ -408,6 +408,7 @@ AffThrPlaceDeprecated "KMP_PLACE_THREADS \"o\" offset designator deprecat
AffUsingHwloc "%1$s: Affinity capable, using hwloc."
AffIgnoringHwloc "%1$s: Ignoring hwloc mechanism."
AffHwlocErrorOccurred "%1$s: Hwloc failed in %2$s. Relying on internal affinity mechanisms."
EnvSerialWarn "%1$s must be set prior to OpenMP runtime library initialization; ignored."
# --------------------------------------------------------------------------------------------------
+1
View File
@@ -140,6 +140,7 @@
extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void);
extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void);
extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *);
extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int);
/* Intel affinity API */
typedef void * kmp_affinity_mask_t;
+5
View File
@@ -410,6 +410,11 @@
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity
+7
View File
@@ -391,6 +391,11 @@
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num) bind(c)
import
integer (kind=omp_integer_kind), value :: num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_set_affinity
@@ -544,6 +549,7 @@
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_stacksize_s
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_blocktime
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_library
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_disp_num_buffers
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_affinity
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_affinity
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_affinity_max_proc
@@ -615,6 +621,7 @@
!$omp declare target(kmp_get_stacksize_s )
!$omp declare target(kmp_get_blocktime )
!$omp declare target(kmp_get_library )
!$omp declare target(kmp_set_disp_num_buffers )
!$omp declare target(kmp_set_affinity )
!$omp declare target(kmp_get_affinity )
!$omp declare target(kmp_get_affinity_max_proc )
+3 -2
View File
@@ -1050,8 +1050,7 @@ extern int __kmp_place_num_threads_per_core;
#define KMP_MAX_NEXT_WAIT (INT_MAX/2)
#define KMP_DEFAULT_NEXT_WAIT 1024U
// max possible dynamic loops in concurrent execution per team
#define KMP_MAX_DISP_BUF 7
#define KMP_DFLT_DISP_NUM_BUFF 7
#define KMP_MAX_ORDERED 8
#define KMP_MAX_FIELDS 32
@@ -2806,6 +2805,7 @@ extern kmp_uint32 __kmp_init_mxcsr; /* init thread's mxscr */
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
extern int __kmp_dflt_max_active_levels; /* max_active_levels for nested parallelism enabled by default a la OMP_MAX_ACTIVE_LEVELS */
extern int __kmp_dispatch_num_buffers; /* max possible dynamic loops in concurrent execution per team */
#if KMP_NESTED_HOT_TEAMS
extern int __kmp_hot_teams_mode;
extern int __kmp_hot_teams_max_level;
@@ -3623,6 +3623,7 @@ KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize(int);
KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize_s(size_t);
KMP_EXPORT void KMPC_CONVENTION kmpc_set_library(int);
KMP_EXPORT void KMPC_CONVENTION kmpc_set_defaults(char const *);
KMP_EXPORT void KMPC_CONVENTION kmpc_set_disp_num_buffers(int);
#ifdef __cplusplus
}
+13 -4
View File
@@ -1653,6 +1653,15 @@ kmpc_set_defaults( char const * str )
__kmp_aux_set_defaults( str, KMP_STRLEN( str ) );
}
void
kmpc_set_disp_num_buffers( int arg )
{
// ignore after initialization because some teams have already
// allocated dispatch buffers
if( __kmp_init_serial == 0 && arg > 0 )
__kmp_dispatch_num_buffers = arg;
}
int
kmpc_set_affinity_mask_proc( int proc, void **mask )
{
@@ -3061,7 +3070,7 @@ __kmpc_doacross_init(ident_t *loc, int gtid, int num_dims, struct kmp_dim * dims
}
KMP_DEBUG_ASSERT(team->t.t_nproc > 1);
idx = pr_buf->th_doacross_buf_idx++; // Increment index of shared buffer for the next loop
sh_buf = &team->t.t_disp_buffer[idx % KMP_MAX_DISP_BUF];
sh_buf = &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers];
// Save bounds info into allocated private buffer
KMP_DEBUG_ASSERT(pr_buf->th_doacross_info == NULL);
@@ -3111,7 +3120,7 @@ __kmpc_doacross_init(ident_t *loc, int gtid, int num_dims, struct kmp_dim * dims
}
KMP_DEBUG_ASSERT(trace_count > 0);
// Check if shared buffer is not occupied by other loop (idx - KMP_MAX_DISP_BUF)
// Check if shared buffer is not occupied by other loop (idx - __kmp_dispatch_num_buffers)
if( idx != sh_buf->doacross_buf_idx ) {
// Shared buffer is occupied, wait for it to be free
__kmp_wait_yield_4( (kmp_uint32*)&sh_buf->doacross_buf_idx, idx, __kmp_eq_4, NULL );
@@ -3300,14 +3309,14 @@ __kmpc_doacross_fini(ident_t *loc, int gtid)
if( num_done == th->th.th_team_nproc ) {
// we are the last thread, need to free shared resources
int idx = pr_buf->th_doacross_buf_idx - 1;
dispatch_shared_info_t *sh_buf = &team->t.t_disp_buffer[idx % KMP_MAX_DISP_BUF];
dispatch_shared_info_t *sh_buf = &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers];
KMP_DEBUG_ASSERT(pr_buf->th_doacross_info[1] == (kmp_int64)&sh_buf->doacross_num_done);
KMP_DEBUG_ASSERT(num_done == (kmp_int64)sh_buf->doacross_num_done);
KMP_DEBUG_ASSERT(idx == sh_buf->doacross_buf_idx);
__kmp_thread_free(th, (void*)sh_buf->doacross_flags);
sh_buf->doacross_flags = NULL;
sh_buf->doacross_num_done = 0;
sh_buf->doacross_buf_idx += KMP_MAX_DISP_BUF; // free buffer for future re-use
sh_buf->doacross_buf_idx += __kmp_dispatch_num_buffers; // free buffer for future re-use
}
// free private resources (need to keep buffer index forever)
__kmp_thread_free(th, (void*)pr_buf->th_doacross_info);
+3 -3
View File
@@ -656,9 +656,9 @@ __kmp_dispatch_init(
/* What happens when number of threads changes, need to resize buffer? */
pr = reinterpret_cast< dispatch_private_info_template< T > * >
( &th -> th.th_dispatch -> th_disp_buffer[ my_buffer_index % KMP_MAX_DISP_BUF ] );
( &th -> th.th_dispatch -> th_disp_buffer[ my_buffer_index % __kmp_dispatch_num_buffers ] );
sh = reinterpret_cast< dispatch_shared_info_template< UT > volatile * >
( &team -> t.t_disp_buffer[ my_buffer_index % KMP_MAX_DISP_BUF ] );
( &team -> t.t_disp_buffer[ my_buffer_index % __kmp_dispatch_num_buffers ] );
}
/* Currently just ignore the monotonic and non-monotonic modifiers (the compiler isn't producing them
@@ -2150,7 +2150,7 @@ __kmp_dispatch_next(
KMP_MB(); /* Flush all pending memory write invalidates. */
sh -> buffer_index += KMP_MAX_DISP_BUF;
sh -> buffer_index += __kmp_dispatch_num_buffers;
KD_TRACE(100, ("__kmp_dispatch_next: T#%d change buffer_index:%d\n",
gtid, sh->buffer_index) );
+13
View File
@@ -215,6 +215,19 @@ FTN_GET_LIBRARY (void)
#endif
}
void FTN_STDCALL
FTN_SET_DISP_NUM_BUFFERS( int KMP_DEREF arg )
{
#ifdef KMP_STUB
; // empty routine
#else
// ignore after initialization because some teams have already
// allocated dispatch buffers
if( __kmp_init_serial == 0 && (KMP_DEREF arg) > 0 )
__kmp_dispatch_num_buffers = KMP_DEREF arg;
#endif
}
int FTN_STDCALL
FTN_SET_AFFINITY( void **mask )
{
+4
View File
@@ -35,6 +35,7 @@
#define FTN_SET_LIBRARY kmp_set_library
#define FTN_GET_LIBRARY kmp_get_library
#define FTN_SET_DEFAULTS kmp_set_defaults
#define FTN_SET_DISP_NUM_BUFFERS kmp_set_disp_num_buffers
#define FTN_SET_AFFINITY kmp_set_affinity
#define FTN_GET_AFFINITY kmp_get_affinity
#define FTN_GET_AFFINITY_MAX_PROC kmp_get_affinity_max_proc
@@ -152,6 +153,7 @@
#define FTN_SET_LIBRARY kmp_set_library_
#define FTN_GET_LIBRARY kmp_get_library_
#define FTN_SET_DEFAULTS kmp_set_defaults_
#define FTN_SET_DISP_NUM_BUFFERS kmp_set_disp_num_buffers_
#define FTN_SET_AFFINITY kmp_set_affinity_
#define FTN_GET_AFFINITY kmp_get_affinity_
#define FTN_GET_AFFINITY_MAX_PROC kmp_get_affinity_max_proc_
@@ -270,6 +272,7 @@
#define FTN_SET_LIBRARY KMP_SET_LIBRARY
#define FTN_GET_LIBRARY KMP_GET_LIBRARY
#define FTN_SET_DEFAULTS KMP_SET_DEFAULTS
#define FTN_SET_DISP_NUM_BUFFERS KMP_SET_DISP_NUM_BUFFERS
#define FTN_SET_AFFINITY KMP_SET_AFFINITY
#define FTN_GET_AFFINITY KMP_GET_AFFINITY
#define FTN_GET_AFFINITY_MAX_PROC KMP_GET_AFFINITY_MAX_PROC
@@ -388,6 +391,7 @@
#define FTN_SET_LIBRARY KMP_SET_LIBRARY_
#define FTN_GET_LIBRARY KMP_GET_LIBRARY_
#define FTN_SET_DEFAULTS KMP_SET_DEFAULTS_
#define FTN_SET_DISP_NUM_BUFFERS KMP_SET_DISP_NUM_BUFFERS_
#define FTN_SET_AFFINITY KMP_SET_AFFINITY_
#define FTN_GET_AFFINITY KMP_GET_AFFINITY_
#define FTN_GET_AFFINITY_MAX_PROC KMP_GET_AFFINITY_MAX_PROC_
+1
View File
@@ -128,6 +128,7 @@ int __kmp_dflt_team_nth_ub = 0;
int __kmp_tp_capacity = 0;
int __kmp_tp_cached = 0;
int __kmp_dflt_nested = FALSE;
int __kmp_dispatch_num_buffers = KMP_DFLT_DISP_NUM_BUFF;
int __kmp_dflt_max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT; /* max_active_levels limit */
#if KMP_NESTED_HOT_TEAMS
int __kmp_hot_teams_mode = 0; /* 0 - free extra threads when reduced */
+5 -5
View File
@@ -489,7 +489,7 @@ __kmp_print_thread_storage_map( kmp_info_t *thr, int gtid )
static void
__kmp_print_team_storage_map( const char *header, kmp_team_t *team, int team_id, int num_thr )
{
int num_disp_buff = team->t.t_max_nproc > 1 ? KMP_MAX_DISP_BUF : 2;
int num_disp_buff = team->t.t_max_nproc > 1 ? __kmp_dispatch_num_buffers : 2;
__kmp_print_storage_map_gtid( -1, team, team + 1, sizeof(kmp_team_t), "%s_%d",
header, team_id );
@@ -2967,7 +2967,7 @@ static void
__kmp_allocate_team_arrays(kmp_team_t *team, int max_nth)
{
int i;
int num_disp_buff = max_nth > 1 ? KMP_MAX_DISP_BUF : 2;
int num_disp_buff = max_nth > 1 ? __kmp_dispatch_num_buffers : 2;
team->t.t_threads = (kmp_info_t**) __kmp_allocate( sizeof(kmp_info_t*) * max_nth );
team->t.t_disp_buffer = (dispatch_shared_info_t*)
__kmp_allocate( sizeof(dispatch_shared_info_t) * num_disp_buff );
@@ -4040,7 +4040,7 @@ __kmp_initialize_info( kmp_info_t *this_thr, kmp_team_t *team, int tid, int gtid
* Use team max_nproc since this will never change for the team.
*/
size_t disp_size = sizeof( dispatch_private_info_t ) *
( team->t.t_max_nproc == 1 ? 1 : KMP_MAX_DISP_BUF );
( team->t.t_max_nproc == 1 ? 1 : __kmp_dispatch_num_buffers );
KD_TRACE( 10, ("__kmp_initialize_info: T#%d max_nproc: %d\n", gtid, team->t.t_max_nproc ) );
KMP_ASSERT( dispatch );
KMP_DEBUG_ASSERT( team->t.t_dispatch );
@@ -4055,7 +4055,7 @@ __kmp_initialize_info( kmp_info_t *this_thr, kmp_team_t *team, int tid, int gtid
if ( __kmp_storage_map ) {
__kmp_print_storage_map_gtid( gtid, &dispatch->th_disp_buffer[ 0 ],
&dispatch->th_disp_buffer[ team->t.t_max_nproc == 1 ? 1 : KMP_MAX_DISP_BUF ],
&dispatch->th_disp_buffer[ team->t.t_max_nproc == 1 ? 1 : __kmp_dispatch_num_buffers ],
disp_size, "th_%d.th_dispatch.th_disp_buffer "
"(team_%d.t_dispatch[%d].th_disp_buffer)",
gtid, team->t.t_id, gtid );
@@ -6997,7 +6997,7 @@ __kmp_internal_fork( ident_t *id, int gtid, kmp_team_t *team )
KMP_DEBUG_ASSERT( team->t.t_disp_buffer );
if ( team->t.t_max_nproc > 1 ) {
int i;
for (i = 0; i < KMP_MAX_DISP_BUF; ++i) {
for (i = 0; i < __kmp_dispatch_num_buffers; ++i) {
team->t.t_disp_buffer[ i ].buffer_index = i;
#if OMP_41_ENABLED
team->t.t_disp_buffer[i].doacross_buf_idx = i;
+18
View File
@@ -1197,6 +1197,23 @@ __kmp_stg_print_max_task_priority(kmp_str_buf_t *buffer, char const *name, void
} // __kmp_stg_print_max_task_priority
#endif // OMP_41_ENABLED
// -------------------------------------------------------------------------------------------------
// KMP_DISP_NUM_BUFFERS
// -------------------------------------------------------------------------------------------------
static void
__kmp_stg_parse_disp_buffers( char const * name, char const * value, void * data ) {
if ( TCR_4(__kmp_init_serial) ) {
KMP_WARNING( EnvSerialWarn, name );
return;
} // read value before serial initialization only
__kmp_stg_parse_int( name, value, 1, KMP_MAX_NTH, & __kmp_dispatch_num_buffers );
} // __kmp_stg_parse_disp_buffers
static void
__kmp_stg_print_disp_buffers( kmp_str_buf_t * buffer, char const * name, void * data ) {
__kmp_stg_print_int( buffer, name, __kmp_dispatch_num_buffers );
} // __kmp_stg_print_disp_buffers
#if KMP_NESTED_HOT_TEAMS
// -------------------------------------------------------------------------------------------------
// KMP_HOT_TEAMS_MAX_LEVEL, KMP_HOT_TEAMS_MODE
@@ -4646,6 +4663,7 @@ static kmp_setting_t __kmp_stg_table[] = {
#endif
{ "OMP_THREAD_LIMIT", __kmp_stg_parse_all_threads, __kmp_stg_print_all_threads, NULL, 0, 0 },
{ "OMP_WAIT_POLICY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy, NULL, 0, 0 },
{ "KMP_DISP_NUM_BUFFERS", __kmp_stg_parse_disp_buffers, __kmp_stg_print_disp_buffers, NULL, 0, 0 },
#if KMP_NESTED_HOT_TEAMS
{ "KMP_HOT_TEAMS_MAX_LEVEL", __kmp_stg_parse_hot_teams_level, __kmp_stg_print_hot_teams_level, NULL, 0, 0 },
{ "KMP_HOT_TEAMS_MODE", __kmp_stg_parse_hot_teams_mode, __kmp_stg_print_hot_teams_mode, NULL, 0, 0 },
+2
View File
@@ -41,6 +41,7 @@
#define kmp_set_blocktime kmpc_set_blocktime
#define kmp_set_library kmpc_set_library
#define kmp_set_defaults kmpc_set_defaults
#define kmp_set_disp_num_buffers kmpc_set_disp_num_buffers
#define kmp_malloc kmpc_malloc
#define kmp_aligned_malloc kmpc_aligned_malloc
#define kmp_calloc kmpc_calloc
@@ -100,6 +101,7 @@ void kmp_set_stacksize_s( size_t arg ) { i; __kmps_set_stacksize( arg ); }
void kmp_set_blocktime( omp_int_t arg ) { i; __kmps_set_blocktime( arg ); }
void kmp_set_library( omp_int_t arg ) { i; __kmps_set_library( arg ); }
void kmp_set_defaults( char const * str ) { i; }
void kmp_set_disp_num_buffers( omp_int_t arg ) { i; }
/* KMP memory management functions. */
void * kmp_malloc( size_t size ) { i; return malloc( size ); }
+76
View File
@@ -0,0 +1,76 @@
// RUN: %libomp-compile && env KMP_DISP_NUM_BUFFERS=0 %libomp-run
// RUN: env KMP_DISP_NUM_BUFFERS=1 %libomp-run && env KMP_DISP_NUM_BUFFERS=3 %libomp-run
// RUN: env KMP_DISP_NUM_BUFFERS=4 %libomp-run && env KMP_DISP_NUM_BUFFERS=7 %libomp-run
// RUN: %libomp-compile -DMY_SCHEDULE=guided && env KMP_DISP_NUM_BUFFERS=1 %libomp-run
// RUN: env KMP_DISP_NUM_BUFFERS=3 %libomp-run && env KMP_DISP_NUM_BUFFERS=4 %libomp-run
// RUN: env KMP_DISP_NUM_BUFFERS=7 %libomp-run
#include <stdio.h>
#include <omp.h>
#include <stdlib.h>
#include <limits.h>
#include "omp_testsuite.h"
#define INCR 7
#define MY_MAX 200
#define MY_MIN -200
#define NUM_LOOPS 100
#ifndef MY_SCHEDULE
# define MY_SCHEDULE dynamic
#endif
int a, b, a_known_value, b_known_value;
int test_kmp_set_disp_num_buffers()
{
int success = 1;
a = 0;
b = 0;
// run many small dynamic loops to stress the dispatch buffer system
#pragma omp parallel
{
int i,j;
for (j = 0; j < NUM_LOOPS; j++) {
#pragma omp for schedule(MY_SCHEDULE) nowait
for (i = MY_MIN; i < MY_MAX; i+=INCR) {
#pragma omp atomic
a++;
}
#pragma omp for schedule(MY_SCHEDULE) nowait
for (i = MY_MAX; i >= MY_MIN; i-=INCR) {
#pragma omp atomic
b++;
}
}
}
// detect failure
if (a != a_known_value || b != b_known_value) {
success = 0;
printf("a = %d (should be %d), b = %d (should be %d)\n", a, a_known_value,
b, b_known_value);
}
return success;
}
int main(int argc, char** argv)
{
int i,j;
int num_failed=0;
// figure out the known values to compare with calculated result
a_known_value = 0;
b_known_value = 0;
for (j = 0; j < NUM_LOOPS; j++) {
for (i = MY_MIN; i < MY_MAX; i+=INCR)
a_known_value++;
for (i = MY_MAX; i >= MY_MIN; i-=INCR)
b_known_value++;
}
for(i = 0; i < REPETITIONS; i++) {
if(!test_kmp_set_disp_num_buffers()) {
num_failed++;
}
}
return num_failed;
}
@@ -0,0 +1,91 @@
// RUN: %libomp-compile && %libomp-run 7
// RUN: %libomp-run 0 && %libomp-run -1
// RUN: %libomp-run 1 && %libomp-run 2 && %libomp-run 5
// RUN: %libomp-compile -DMY_SCHEDULE=guided && %libomp-run 7
// RUN: %libomp-run 1 && %libomp-run 2 && %libomp-run 5
#include <stdio.h>
#include <omp.h>
#include <stdlib.h>
#include <limits.h>
#include "omp_testsuite.h"
#define INCR 7
#define MY_MAX 200
#define MY_MIN -200
#ifndef MY_SCHEDULE
# define MY_SCHEDULE dynamic
#endif
int num_disp_buffers, num_loops;
int a, b, a_known_value, b_known_value;
int test_kmp_set_disp_num_buffers()
{
int success = 1;
a = 0;
b = 0;
// run many small dynamic loops to stress the dispatch buffer system
#pragma omp parallel
{
int i,j;
for (j = 0; j < num_loops; j++) {
#pragma omp for schedule(MY_SCHEDULE) nowait
for (i = MY_MIN; i < MY_MAX; i+=INCR) {
#pragma omp atomic
a++;
}
#pragma omp for schedule(MY_SCHEDULE) nowait
for (i = MY_MAX; i >= MY_MIN; i-=INCR) {
#pragma omp atomic
b++;
}
}
}
// detect failure
if (a != a_known_value || b != b_known_value) {
success = 0;
printf("a = %d (should be %d), b = %d (should be %d)\n", a, a_known_value,
b, b_known_value);
}
return success;
}
int main(int argc, char** argv)
{
int i,j;
int num_failed=0;
if (argc != 2) {
fprintf(stderr, "usage: %s num_disp_buffers\n", argv[0]);
exit(1);
}
// set the number of dispatch buffers
num_disp_buffers = atoi(argv[1]);
kmp_set_disp_num_buffers(num_disp_buffers);
// figure out the known values to compare with calculated result
a_known_value = 0;
b_known_value = 0;
// if specified to use bad num_disp_buffers set num_loops
// to something reasonable
if (num_disp_buffers <= 0)
num_loops = 10;
else
num_loops = num_disp_buffers*10;
for (j = 0; j < num_loops; j++) {
for (i = MY_MIN; i < MY_MAX; i+=INCR)
a_known_value++;
for (i = MY_MAX; i >= MY_MIN; i-=INCR)
b_known_value++;
}
for(i = 0; i < REPETITIONS; i++) {
if(!test_kmp_set_disp_num_buffers()) {
num_failed++;
}
}
return num_failed;
}