1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
/* $Source: bitbucket.org:berkeleylab/gasnet.git/tests/testlockcontend.c $
* Description: GASNet lock performance test
* Measures the overhead associated with contended locks
* Copyright 2002, Dan Bonachea <bonachea@cs.berkeley.edu>
* Terms of use are as specified in license.txt
*/
#include <test.h>
#ifndef GASNET_PAR
#error This test can only be built for GASNet PAR configuration
#endif
static gex_Client_t myclient;
static gex_EP_t myep;
static gex_TM_t myteam;
static gex_Segment_t mysegment;
int mynode = 0;
int iters=0;
void *myseg = NULL;
int accuracy = 0;
int maxthreads = 2;
int threads = 1;
void header(const char *desc) {
printf("\n---- %s ----\n"
" Threads Total time Avg. time\n"
" ------- ---------- ---------\n", desc);
}
void report(int threads, int64_t totaltime, int iters) {
char format[80];
snprintf(format, sizeof(format), "%c: %%6i %%%i.%if s %%%i.%if us\n",
TEST_SECTION_NAME(), (4+accuracy), accuracy, (4+accuracy), accuracy);
printf(format, threads, totaltime/1.0E9, (totaltime/1000.0)/iters);
fflush(stdout);
}
/* placed in a function to avoid excessive inlining */
gasnett_tick_t ticktime(void) { return gasnett_ticks_now(); }
uint64_t tickcvt(gasnett_tick_t ticks) { return gasnett_ticks_to_ns(ticks); }
void* thread_fn1(void*);
void* thread_fn2(void*);
void* thread_fn3(void*);
void* thread_fn4(void*);
/* ------------------------------------------------------------------------------------ */
/* This tester measures the performance of contended HSLs and pthread mutexes.
*/
int main(int argc, char **argv) {
GASNET_Safe(gex_Client_Init(&myclient, &myep, &myteam, "testlockcontend", &argc, &argv, 0));
GASNET_Safe(gex_Segment_Attach(&mysegment, myteam, TEST_SEGSZ_REQUEST));
test_init("testlockcontend",1,"(maxthreads) (iters) (accuracy) (test sections)");
if (argc > 1) maxthreads = atoi(argv[1]);
maxthreads = test_thread_limit(maxthreads);
if (maxthreads < 1) {
printf("Threads must be between 1 and %i\n", TEST_MAXTHREADS);
gasnet_exit(-1);
}
if (argc > 2) iters = atoi(argv[2]);
if (!iters) iters = 1000000;
if (argc > 3) accuracy = atoi(argv[3]);
if (!accuracy) accuracy = 3;
if (argc > 4) TEST_SECTION_PARSE(argv[4]);
if (argc > 5) test_usage();
mynode = gex_TM_QueryRank(myteam);
myseg = TEST_MYSEG();
if (mynode == 0) {
printf("Running locks performance test with 1..%i threads and %i iterations...\n",maxthreads,iters);
fflush(stdout);
MSG0("Spawning pthreads...");
if (TEST_SECTION_BEGIN_ENABLED()) {
header("lock/unlock contended pthread mutex (others in thread barrier)");
test_createandjoin_pthreads(threads = maxthreads, &thread_fn1, NULL, 0);
}
if (TEST_SECTION_BEGIN_ENABLED()) {
header("lock/unlock contended HSL (others in thread barrier)");
test_createandjoin_pthreads(threads = maxthreads, &thread_fn2, NULL, 0);
}
if (TEST_SECTION_BEGIN_ENABLED()) {
header("lock/unlock contended pthread mutex (no other threads)");
for (threads=1; threads<=maxthreads; ++threads) {
test_createandjoin_pthreads(threads, &thread_fn3, NULL, 0);
}
}
if (TEST_SECTION_BEGIN_ENABLED()) {
header("lock/unlock contended HSL (no other threads)");
for (threads=1; threads<=maxthreads; ++threads) {
test_createandjoin_pthreads(threads, &thread_fn4, NULL, 0);
}
}
}
BARRIER();
MSG("done.");
gasnet_exit(0);
return 0;
}
/* ------------------------------------------------------------------------------------ */
#undef MSG0
#undef ERR
#define MSG0 THREAD_MSG0(id)
#define ERR THREAD_ERR(id)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char _pad[GASNETT_CACHE_LINE_BYTES] = { 0 }; /* bug 2231 workaround */
gex_HSL_t hsl = GEX_HSL_INITIALIZER;
/* ------------------------------------------------------------------------------------ */
#define TIME_OPERATION_SOME(id, op) \
do { \
PTHREAD_LOCALBARRIER(threads); \
{ int i, _thr, _iters = iters, _warmupiters = MAX(1,iters/10);\
gasnett_tick_t start,end; /* use ticks interface */ \
for (i=0; i < _warmupiters; i++) { op; } /* warm-up */ \
for (_thr = 1; _thr <= threads; ++_thr) { \
PTHREAD_LOCALBARRIER(threads); \
start = ticktime(); \
if (id < _thr) for (i=0; i < _iters; i++) { op; } \
PTHREAD_LOCALBARRIER(threads); \
end = ticktime(); \
if (!id) \
report(_thr, tickcvt(end - start), iters); \
} \
} \
} while (0)
void * thread_fn1(void *arg) { GASNET_BEGIN_FUNCTION();
int id = (int)(uintptr_t)arg;
TIME_OPERATION_SOME(id, { pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex); });
return NULL;
}
void * thread_fn2(void *arg) { GASNET_BEGIN_FUNCTION();
int id = (int)(uintptr_t)arg;
TIME_OPERATION_SOME(id, { gex_HSL_Lock(&hsl); gex_HSL_Unlock(&hsl); });
return NULL;
}
/* ------------------------------------------------------------------------------------ */
#define TIME_OPERATION_ALL(id, op) \
do { \
PTHREAD_LOCALBARRIER(threads); \
{ int i, _iters = iters, _warmupiters = MAX(1,iters/10); \
gasnett_tick_t start,end; /* use ticks interface */ \
for (i=0; i < _warmupiters; i++) { op; } /* warm-up */ \
PTHREAD_LOCALBARRIER(threads); \
start = ticktime(); \
for (i=0; i < _iters; i++) { op; } \
PTHREAD_LOCALBARRIER(threads); \
end = ticktime(); \
if (!id) \
report(threads, tickcvt(end - start), iters); \
} \
} while (0)
void * thread_fn3(void *arg) { GASNET_BEGIN_FUNCTION();
int id = (int)(uintptr_t)arg;
TIME_OPERATION_ALL(id, { pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex); });
return NULL;
}
void * thread_fn4(void *arg) { GASNET_BEGIN_FUNCTION();
int id = (int)(uintptr_t)arg;
TIME_OPERATION_ALL(id, { gex_HSL_Lock(&hsl); gex_HSL_Unlock(&hsl); });
return NULL;
}
/* ------------------------------------------------------------------------------------ */
|