/******************************************************************************/
/* */
/* Copyright (c) 2008, 2009, 2010 */
/* Computer Architecture Group (CAG) */
/* University of A Coruña, Spain */
/* (http://gac.des.udc.es) */
/* Galicia Supercomputing Center (CESGA) */
/* (http://www.cesga.es) */
/* Hewlett-Packard Spain (HP) */
/* (http://www.hp.es) */
/* */
/* This file is part of UPC Operations Microbenchmarking Suite (UOMS). */
/* */
/* UOMS is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU Lesser General Public License as published */
/* by the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* UOMS is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with UOMS. If not, see . */
/* */
/******************************************************************************/
/******************************************************************************/
/* */
/* FUNDING: This development has been funded by Hewlett-Packard Spain */
/* */
/* Project Name: */
/* UPCHACO (2008-2011) */
/* Subproject: */
/* Improving UPC Usability and Performance in Constellation Systems: */
/* Implementation/Extensions of UPC Libraries. */
/* (UPCPUProject -> UPC Performance and Usability Project) */
/* */
/******************************************************************************/
/******************************************************************************
For further documentation, see
[1] Files under doc/
*******************************************************************************/
#include
#include
#include
#include
#include
#include
#include "defines.h"
#include "headers.h"
#define roundtoint(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5))
extern char * valid_bms[NUM_BMS];
extern upc_op_t reduce_op;
long maxsize, minsize;
/*
Set benchmarks names
*/
void set_bms_names(){
valid_bms[FORALL_R] = "upc_forall read";
valid_bms[FORALL_W] = "upc_forall write";
valid_bms[FORALL_RW] = "upc_forall read+write";
valid_bms[FOR_R] = "for read";
valid_bms[FOR_W] = "for write";
valid_bms[FOR_RW] = "for read+write";
valid_bms[BARRIER] = "upc_barrier";
valid_bms[BROADCAST] = "upc_all_broadcast";
valid_bms[SCATTER] = "upc_all_scatter";
valid_bms[GATHER] = "upc_all_gather";
valid_bms[GATHERALL] = "upc_all_gather_all";
valid_bms[EXCHANGE] = "upc_all_exchange";
valid_bms[PERMUTE] = "upc_all_permute";
valid_bms[MEMGET] = "upc_memget";
valid_bms[MEMPUT] = "upc_memput";
valid_bms[MEMCPY] = "upc_memcpy";
valid_bms[LMEMGET] = "local_upc_memget";
valid_bms[LMEMPUT] = "local_upc_memput";
valid_bms[LMEMCPY] = "local_upc_memcpy";
valid_bms[SMEMCPY] = "memcpy";
valid_bms[MEMMOVE] = "memmove";
valid_bms[ALLALLOC] = "upc_all_alloc";
valid_bms[FREE] = "upc_free";
valid_bms[REDUCE_C] = "upc_all_reduceC";
valid_bms[PREFIX_REDUCE_C] = "upc_all_prefix_reduceC";
valid_bms[REDUCE_UC] = "upc_all_reduceUC";
valid_bms[PREFIX_REDUCE_UC] = "upc_all_prefix_reduceUC";
valid_bms[REDUCE_S] = "upc_all_reduceS";
valid_bms[PREFIX_REDUCE_S] = "upc_all_prefix_reduceS";
valid_bms[REDUCE_US] = "upc_all_reduceUS";
valid_bms[PREFIX_REDUCE_US] = "upc_all_prefix_reduceUS";
valid_bms[REDUCE_I] = "upc_all_reduceI";
valid_bms[PREFIX_REDUCE_I] = "upc_all_prefix_reduceI";
valid_bms[REDUCE_UI] = "upc_all_reduceUI";
valid_bms[PREFIX_REDUCE_UI] = "upc_all_prefix_reduceUI";
valid_bms[REDUCE_L] = "upc_all_reduceL";
valid_bms[PREFIX_REDUCE_L] = "upc_all_prefix_reduceL";
valid_bms[REDUCE_UL] = "upc_all_reduceUL";
valid_bms[PREFIX_REDUCE_UL] = "upc_all_prefix_reduceUL";
valid_bms[REDUCE_F] = "upc_all_reduceF";
valid_bms[PREFIX_REDUCE_F] = "upc_all_prefix_reduceF";
valid_bms[REDUCE_D] = "upc_all_reduceD";
valid_bms[PREFIX_REDUCE_D] = "upc_all_prefix_reduceD";
valid_bms[REDUCE_LD] = "upc_all_reduceLD";
valid_bms[PREFIX_REDUCE_LD] = "upc_all_prefix_reduceLD";
#ifdef ASYNC_MEM_TEST
valid_bms[AMEMGET] = "upc_memget_async";
valid_bms[AMEMPUT] = "upc_memput_async";
valid_bms[AMEMCPY] = "upc_memcpy_async";
valid_bms[ALMEMGET] = "local_upc_memget_async";
valid_bms[ALMEMPUT] = "local_upc_memput_async";
valid_bms[ALMEMCPY] = "local_upc_memcpy_async";
#endif
#ifdef ASYNCI_MEM_TEST
valid_bms[AIMEMGET] = "upc_memget_asynci";
valid_bms[AIMEMPUT] = "upc_memput_asynci";
valid_bms[AIMEMCPY] = "upc_memcpy_asynci";
valid_bms[AILMEMGET] = "local_upc_memget_asynci";
valid_bms[AILMEMPUT] = "local_upc_memput_asynci";
valid_bms[AILMEMCPY] = "local_upc_memcpy_asynci";
#endif
}
/*
Set min size
*/
int set_min_size(char *size){
if(size[0] >= '0' && size[0] <= '9'){
errno = 0;
minsize = strtol(size,NULL,10);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** minsize (%s) not valid: ",size);
perror(NULL);
}
return -1;
}
}
else{
if(MYTHREAD == 0){
fprintf(stderr,"*** minsize (%s) not valid",size);
}
return -1;
}
return 0;
}
/*
Set max size
*/
int set_max_size(char *size){
if(size[0] >= '0' && size[0] <= '9'){
errno = 0;
maxsize = strtol(size,NULL,10);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** maxsize (%s) not valid: ",size);
perror(NULL);
}
return -1;
}
}
else{
if(MYTHREAD == 0){
fprintf(stderr,"*** maxsize (%s) not valid",size);
}
return -1;
}
return 0;
}
/*
Set reduce operation
*/
int set_reduce_op(char *operation){
extern char *char_reduce_op;
if(strcmp(operation,"UPC_ADD") == 0){
reduce_op = UPC_ADD;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_MULT") == 0){
reduce_op = UPC_MULT;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_AND") == 0){
reduce_op = UPC_AND;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_OR") == 0){
reduce_op = UPC_OR;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_XOR") == 0){
reduce_op = UPC_XOR;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_LOGAND") == 0){
reduce_op = UPC_LOGAND;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_LOGOR") == 0){
reduce_op = UPC_LOGOR;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_MIN") == 0){
reduce_op = UPC_MIN;
char_reduce_op = operation;
}
else if(strcmp(operation,"UPC_MAX") == 0){
reduce_op = UPC_MAX;
char_reduce_op = operation;
}
else{
return -1;
}
return 0;
}
/*
Set synchronization mode
*/
int set_sync_mode(char *mode){
extern upc_flag_t sync_mode;
extern char * char_sync_mode;
if(strcmp(mode,"UPC_IN_ALLSYNC|UPC_OUT_ALLSYNC") == 0){
sync_mode = UPC_IN_ALLSYNC|UPC_OUT_ALLSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_ALLSYNC|UPC_OUT_MYSYNC") == 0){
sync_mode = UPC_IN_ALLSYNC|UPC_OUT_MYSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_ALLSYNC|UPC_OUT_NOSYNC") == 0){
sync_mode = UPC_IN_ALLSYNC|UPC_OUT_NOSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_MYSYNC|UPC_OUT_ALLSYNC") == 0){
sync_mode = UPC_IN_MYSYNC|UPC_OUT_ALLSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_MYSYNC|UPC_OUT_MYSYNC") == 0){
sync_mode = UPC_IN_MYSYNC|UPC_OUT_MYSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_MYSYNC|UPC_OUT_NOSYNC") == 0){
sync_mode = UPC_IN_MYSYNC|UPC_OUT_NOSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_NOSYNC|UPC_OUT_ALLSYNC") == 0){
sync_mode = UPC_IN_NOSYNC|UPC_OUT_ALLSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_NOSYNC|UPC_OUT_MYSYNC") == 0){
sync_mode = UPC_IN_NOSYNC|UPC_OUT_MYSYNC;
char_sync_mode = mode;
}
else if(strcmp(mode,"UPC_IN_NOSYNC|UPC_OUT_NOSYNC") == 0){
sync_mode = UPC_IN_NOSYNC|UPC_OUT_NOSYNC;
char_sync_mode = mode;
}
else{
return -1;
}
return 0;
}
/*
Set benchmark list
*/
void set_bms(int alternative_bm_list, char *bm_file){
extern int *bm_list;
extern int num_bms;
FILE *fd;
/*
Default procedure
*/
if(alternative_bm_list == 0){
num_bms = NUM_BMS;
errno = 0;
bm_list = malloc(num_bms*sizeof(int));
if(errno != 0){
if(MYTHREAD == 0){
/*
Just in case you want to run the benchmark in a toaster or someone/something steal all your memory ;-)
*/
fprintf(stderr,"*** Unable to allocate %ld bytes for benchmark list storing: ",num_bms*sizeof(int));
perror(NULL);
}
upc_barrier;
exit(-1);
}
int j = 0;
for(int i = 0; i < num_bms; i++){
if(reduce_op == UPC_AND || reduce_op == UPC_OR || reduce_op == UPC_XOR){
if(i == REDUCE_F || i == PREFIX_REDUCE_F || i == REDUCE_D || i == PREFIX_REDUCE_D || i == REDUCE_LD || i == PREFIX_REDUCE_LD){
continue;
}
}
bm_list[j] = i;
j++;
}
}
/*
User defined
*/
else{
if(bm_file == NULL){
if(MYTHREAD == 0){
fprintf(stderr,"Unexpected error when parsing the benchmarks list file\n");
}
upc_barrier;
exit(-1);
}
errno = 0;
fd = fopen(bm_file,"r");
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error opening file %s: ",bm_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
char curbm[30];
/*
Two phases: one for get the number of benchmarks and the other to actually store them
*/
while (!feof(fd) && fgets(curbm, 30, fd)) {
for(int i = 0; i < 30; i++){
if(curbm[i] == '\n' || curbm[i] == ' '){
curbm[i] = '\0';
}
}
for(int i = 0; i < NUM_BMS; i++){
if(strcmp(curbm,valid_bms[i]) == 0){
num_bms++;
}
}
}
errno = 0;
rewind(fd);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error reading file %s: ",bm_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
errno = 0;
bm_list = malloc(num_bms*sizeof(int));
if(errno != 0){
if(MYTHREAD == 0){
/*
Just in case you want to run the benchmark in a toaster or someone/something steal all your memory ;-)
*/
fprintf(stderr,"*** Unable to allocate %ld bytes for benchmark list storing: ",num_bms*sizeof(int));
perror(NULL);
}
upc_barrier;
exit(-1);
}
int i = 0;
while (!feof(fd) && fgets(curbm, 30, fd)) {
for(int j = 0; j < 30; j++){
if(curbm[j] == '\n' || curbm[j] == ' '){
curbm[j] = '\0';
}
}
for(int j = 0; j < NUM_BMS; j++){
errno = 0;
if(strcmp(curbm,valid_bms[j]) == 0){
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error parsing %s in file %s: ",curbm,bm_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
bm_list[i] = j;
i++;
}
}
}
fclose(fd);
}
if(num_bms < 1){
if(MYTHREAD == 0)
fprintf(stderr,"*** No valid benchmarks specified\n");
exit(-1);
}
}
/*
Set problem sizes
*/
void set_sizes(int alternative_sizes, char *sizes_file){
extern long *sizes;
extern int num_sizes;
FILE *fd;
/*
Default procedure
*/
if(alternative_sizes == 0){
num_sizes = roundtoint(log2((double)maxsize)) - roundtoint(log2((double)minsize)) + 1;
errno = 0;
sizes = malloc(num_sizes*sizeof(long));
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Unable to allocate %ld bytes for message sizes storing: ",num_sizes*sizeof(int));
perror(NULL);
}
upc_barrier;
exit(-1);
}
sizes[0] = minsize;
for(int i = 1; i < num_sizes; i++){
sizes[i] = sizes[i-1]*2;
}
if(sizes[num_sizes-1] > maxsize){
num_sizes--; // We waste sizeof(long) bytes, but probably we can afford it
}
}
/*
User defined
*/
else{
if(sizes_file == NULL){
if(MYTHREAD == 0){
fprintf(stderr,"Unexpected error when parsing the problem sizes file\n");
}
upc_barrier;
exit(-1);
}
errno = 0;
fd = fopen(sizes_file,"r");
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error opening file %s: ",sizes_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
char cursize[20];
/*
Two phases: one for get the number of sizes and the other to actually store them
*/
while (!feof(fd) && fgets(cursize, 20, fd)) {
if(cursize[0] >= '0' && cursize[0] <= '9'){
errno = 0;
strtol(cursize,NULL,10);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error parsing %s in file %s: ",cursize,sizes_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
num_sizes++;
}
else{ /* Silently ignores other lines */
continue;
}
}
errno = 0;
rewind(fd);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error reading file %s: ",sizes_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
errno = 0;
sizes = malloc(num_sizes*sizeof(long));
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Unable to allocate %ld bytes for message sizes storing: ",num_sizes*sizeof(int));
perror(NULL);
}
upc_barrier;
exit(-1);
}
int i = 0;
while (!feof(fd) && fgets(cursize, 20, fd)) {
if(cursize[0] >= '0' && cursize[0] <= '9'){
errno = 0;
sizes[i] = strtol(cursize,NULL,10);
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error parsing %s in file %s: ",cursize,sizes_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
i++;
}
else{ /* Silently ignores other lines */
continue;
}
}
fclose(fd);
}
if(num_sizes < 1){
if(MYTHREAD == 0)
fprintf(stderr,"*** No block sizes specified\n");
exit(-1);
}
}
// Init functions. E.g., initialize permutation array
void UOMS_init(){
int i;
extern shared int perm[THREADS]; //for permutation
//set the permutation array
if ( MYTHREAD == 0 )
{
for (i=0; i0; --i)
{
int j = ((int)rand() >> 3) % i;
int tmp = perm[i];
perm[i] = perm[j];
perm[j] = tmp;
}
}
}
void init(int argc, char **argv){
extern FILE *unit;
extern int cache_invalidation;
extern int warmup;
char *sizes_file = NULL;
char *output_file = NULL;
char *bm_file = NULL;
int alternative_output_file = 0;
int alternative_sizes = 0;
int alternative_bm_list = 0;
minsize = MINSIZE;
maxsize = MAXSIZE;
warmup = 0; // Defaults to off
set_bms_names();
/*
Command line arguments parsing
*/
for(int i = 1; i < argc; i++){
if(strcmp(argv[i],"-off_cache") == 0){
cache_invalidation = 1;
}
else if(strcmp(argv[i],"-msglen") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
else{
alternative_sizes = 1;
sizes_file = argv[i];
}
}
else if(strcmp(argv[i],"-input") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
upc_barrier;
exit(-1);
}
else{
alternative_bm_list = 1;
bm_file = argv[i];
}
}
else if(strcmp(argv[i],"-reduce_op") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
else{
if(set_reduce_op(argv[i]) != 0){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
}
}
else if(strcmp(argv[i],"-sync_mode") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
else{
if(set_sync_mode(argv[i]) != 0){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
}
}
else if(strcmp(argv[i],"-minsize") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
else{
if(set_min_size(argv[i]) != 0){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
}
}
else if(strcmp(argv[i],"-maxsize") == 0){
i++;
if(i == argc){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
else{
if(set_max_size(argv[i]) != 0){
if(MYTHREAD == 0)
print_usage(argv[0]);
exit(-1);
}
}
}
else if(strcmp(argv[i],"-warmup") == 0){
warmup = 1;
}
else if(strcmp(argv[i],"-help") == 0){
if(MYTHREAD == 0)
print_usage(argv[0]);
upc_barrier;
exit(-1);
}
else if(strcmp(argv[i],"-version") == 0){
if(MYTHREAD == 0)
print_version();
upc_barrier;
exit(-1);
}
else{
if(i == argc-1 && argv[i][0] != '-' ){
alternative_output_file = 1;
output_file = argv[i];
}
else{
if(MYTHREAD == 0){
printf("Unrecognized option ignored: %s\n",argv[i]);
}
}
}
}
/*
Optional files checking and parsing
*/
set_sizes(alternative_sizes,sizes_file);
set_bms(alternative_bm_list,bm_file);
/*
Optional output file
*/
if(alternative_output_file){
errno = 0;
unit = fopen(output_file,"w");
if(errno != 0){
if(MYTHREAD == 0){
fprintf(stderr,"*** Error creating or truncating file %s: ",output_file);
perror(NULL);
}
upc_barrier;
exit(-1);
}
}
else{
unit = stdout;
}
UOMS_init();
}