diff --git a/hermit/usr/benchmarks/Makefile b/hermit/usr/benchmarks/Makefile index b48d0dac4..ff879a125 100644 --- a/hermit/usr/benchmarks/Makefile +++ b/hermit/usr/benchmarks/Makefile @@ -1,7 +1,7 @@ ARCH = x86 TARGET=x86_64-hermit MAKE = make -override STRIP_DEBUG = --strip-unneeded --strip-debug +override STRIP_DEBUG = --strip-debug #--strip-unneeded --strip-debug KEEP_DEBUG = --only-keep-debug # Set your own cross compiler tool chain prefix here @@ -43,7 +43,7 @@ endif default: all -all: stream hg +all: stream hg RCCE_pingping RCCE_pingpong stream.o: stream.c @echo [CC] $@ @@ -56,6 +56,20 @@ stream: stream.o $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym +RCCE_pingping: RCCE_pingping.o + @echo [LD] $@ + $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym + $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ + $Qchmod a-x $@.sym + +RCCE_pingpong: RCCE_pingpong.o + @echo [LD] $@ + $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym + $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ + $Qchmod a-x $@.sym + hg: hg.o hist.o rdtsc.o run.o init.o opt.o report.o setup.o @echo [LD] $@ $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< hist.o rdtsc.o run.o init.o opt.o report.o setup.o @@ -69,7 +83,7 @@ clean: veryclean: @echo Propper cleaning benchmarks - $Q$(RM) stream hg *.sym *.o *~ + $Q$(RM) stream hg RCCE_pingping RCCE_pingpong *.sym *.o *~ depend: $Q$(CC_FOR_TARGET) -MM $(CFLAGS_FOR_TARGET) *.c > Makefile.dep diff --git a/hermit/usr/benchmarks/RCCE_pingping.c b/hermit/usr/benchmarks/RCCE_pingping.c new file mode 100644 index 000000000..43c076e0f --- /dev/null +++ b/hermit/usr/benchmarks/RCCE_pingping.c @@ -0,0 +1,145 @@ + +/* + * Copyright 2010 Carsten Clauss, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "RCCE.h" + +#undef _CACHE_WARM_UP_ +#undef _ERROR_CHECK_ + +#define MAXBUFSIZE 1024*1024*4 +#define DEFAULTLEN 1024 +#define NUMROUNDS 10000 + + +char send_buffer[MAXBUFSIZE+1]; +char recv_buffer[MAXBUFSIZE+1]; +char dummy = 0; + +int RCCE_APP(int argc, char **argv) +{ + int i; + int num_ranks; + int remote_rank, my_rank; + int numrounds = NUMROUNDS; + int maxlen = DEFAULTLEN; + int length; + int round; + double timer; + RCCE_SEND_REQUEST send_request; + RCCE_RECV_REQUEST recv_request; + + RCCE_init(&argc, &argv); + + my_rank = RCCE_ue(); + num_ranks = RCCE_num_ues(); + + if(argc > 1) numrounds = atoi(argv[1]); + + if(numrounds < 1) + { + if(my_rank == 0) fprintf(stderr, "Pingping needs at least 1 round; try again\n"); + exit(-1); + } + + if(argc > 2) maxlen = atoi(argv[2]); + + if(maxlen < 1) + { + if(my_rank == 0) fprintf(stderr, "Illegal message size: %s; try again\n", argv[2]); + exit(-1); + } + else if(maxlen > MAXBUFSIZE) + { + if(my_rank == 0) fprintf(stderr, "Message size %d is too big; try again\n", maxlen); + exit(-1); + } + + if(num_ranks != 2) + { + if(my_rank == 0) fprintf(stderr, "Pingping needs exactly two UEs; try again\n"); + exit(-1); + } + + remote_rank = (my_rank + 1) % 2; + + if(my_rank == 0) printf("#bytes\t\tusec\t\tMB/sec\n"); + + for(length=1; length <= maxlen; length*=2) + { +#ifdef _CACHE_WARM_UP_ + for(i=0; i < length; i++) + { + /* cache warm-up: */ + dummy += send_buffer[i]; + dummy += recv_buffer[i]; + } +#endif + + /* synchronize before starting PING-PING: */ + RCCE_barrier(&RCCE_COMM_WORLD); + + for(round=0; round < numrounds+1; round++) + { + +#ifdef _ERROR_CHECK_ + for(i=0; i < length; i++) + { + send_buffer[i] = (i+length+round) % 127; + } +#endif + + /* send PING: */ + RCCE_isend(send_buffer, length, remote_rank, &send_request); + + /* recv PING: */ + RCCE_irecv(recv_buffer, length, remote_rank, &recv_request); + + /* wait for completion: */ + RCCE_isend_wait(&send_request); + RCCE_irecv_wait(&recv_request); + + /* start timer: */ + if(round==0) timer = RCCE_wtime(); + +#ifdef _ERROR_CHECK_ + for(i=0; i < length; i++) + { + if(recv_buffer[i] != (i+length+round) % 127) + { + fprintf(stderr, "ERROR: %d VS %d\n", recv_buffer[i], (i+length+round) % 127); + exit(-1); + } + } +#endif + } + + /* stop timer: */ + timer = RCCE_wtime() - timer; + + if(my_rank == 0) printf("%d\t\t%1.2lf\t\t%1.2lf\n", length, timer/(numrounds)*1000000, (length / (timer/(numrounds))) / (1024*1024) ); + } + + RCCE_finalize(); + + return 0; +} + diff --git a/hermit/usr/benchmarks/RCCE_pingpong.c b/hermit/usr/benchmarks/RCCE_pingpong.c new file mode 100644 index 000000000..a9d12577a --- /dev/null +++ b/hermit/usr/benchmarks/RCCE_pingpong.c @@ -0,0 +1,181 @@ + +/* + * Copyright 2010 Carsten Clauss, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "RCCE.h" + +#undef _CACHE_WARM_UP_ +#undef _USE_SEPARATED_BUFFERS_ +#undef _ERROR_CHECK_ + +#define MAXBUFSIZE 1024*1024*4 +#define DEFAULTLEN 1024 +#define NUMROUNDS 10000 + + +#ifdef _USE_SEPARATED_BUFFERS_ +char send_buffer[MAXBUFSIZE+1]; +char recv_buffer[MAXBUFSIZE+1]; +#else +#define send_buffer buffer +#define recv_buffer buffer +char buffer[MAXBUFSIZE+1]; +#endif +char dummy = 0; + +int RCCE_APP(int argc, char **argv) +{ + int i; + int num_ranks; + int remote_rank, my_rank; + int numrounds = NUMROUNDS; + int maxlen = DEFAULTLEN; + int length; + int round; + int ircce_mode = 0; + double timer; + RCCE_SEND_REQUEST rcce_send_req; + RCCE_RECV_REQUEST rcce_recv_req; + + RCCE_init(&argc, &argv); + + my_rank = RCCE_ue(); + num_ranks = RCCE_num_ues(); + + if(argc > 1) numrounds = atoi(argv[1]); + + if(numrounds < 1) + { + if(my_rank == 0) fprintf(stderr, "Pingpong needs at least 1 round; try again\n"); + exit(-1); + } + + if(argc > 2) maxlen = atoi(argv[2]); + + if(maxlen < 1) + { + if(my_rank == 0) fprintf(stderr, "Illegal message size: %s; try again\n", argv[2]); + exit(-1); + } + else if(maxlen > MAXBUFSIZE) + { + if(my_rank == 0) fprintf(stderr, "Message size %d is too big; try again\n", maxlen); + exit(-1); + } + + if(argc > 3) ircce_mode = 1; + + if(num_ranks != 2) + { + if(my_rank == 0) fprintf(stderr, "Pingpong needs exactly two UEs; try again\n"); + exit(-1); + + } + + remote_rank = (my_rank + 1) % 2; + + if(my_rank == 0) printf("#bytes\t\tusec\t\tMB/sec\n"); + + for(length=1; length <= maxlen; length*=2) + { + +#ifdef _CACHE_WARM_UP_ + for(i=0; i < length; i++) + { + /* cache warm-up: */ + dummy += send_buffer[i]; + dummy += recv_buffer[i]; + } +#endif + + /* synchronize before starting PING-PONG: */ + RCCE_barrier(&RCCE_COMM_WORLD); + + for(round=0; round < numrounds+1; round++) + { + +#ifdef _ERROR_CHECK_ + for(i=0; i < length; i++) + { + send_buffer[i] = (i+length+round) % 127; + } +#endif + + if(my_rank == 0) + { + /* send PING: */ + if(ircce_mode) { + RCCE_isend(send_buffer, length, remote_rank, &rcce_send_req); + RCCE_isend_wait(&rcce_send_req); + } else + RCCE_send(send_buffer, length, remote_rank); + + /* recv PONG: */ + if(ircce_mode) { + RCCE_irecv(recv_buffer, length, remote_rank, &rcce_recv_req); + RCCE_irecv_wait(&rcce_recv_req); + } else + RCCE_recv(recv_buffer, length, remote_rank); + } + else + { + /* recv PING: */ + if(ircce_mode) { + RCCE_irecv(recv_buffer, length, remote_rank, &rcce_recv_req); + RCCE_irecv_wait(&rcce_recv_req); + } else + RCCE_recv(recv_buffer, length, remote_rank); + + /* send PONG: */ + if(ircce_mode) { + RCCE_isend(send_buffer, length, remote_rank, &rcce_send_req); + RCCE_isend_wait(&rcce_send_req); + } else + RCCE_send(send_buffer, length, remote_rank); + } + + /* start timer: */ + if(round == 0) timer = RCCE_wtime(); + +#ifdef _ERROR_CHECK_ + for(i=0; i < length; i++) + { + if(recv_buffer[i] != (i+length+round) % 127) + { + fprintf(stderr, "ERROR: %d VS %d\n", recv_buffer[i], (i+length+round) % 127); + exit(-1); + } + } +#endif + } + + /* stop timer: */ + timer = RCCE_wtime() - timer; + + if(my_rank == 0) printf("%d\t\t%1.2lf\t\t%1.2lf\n", length, timer/(2.0*numrounds)*1000000, (length / (timer/(2.0*numrounds))) / (1024*1024) ); + fflush(stdout); + } + + RCCE_finalize(); + + return 0; +} + diff --git a/hermit/usr/tests/Makefile b/hermit/usr/tests/Makefile index f7435aad3..002cbd06d 100644 --- a/hermit/usr/tests/Makefile +++ b/hermit/usr/tests/Makefile @@ -43,7 +43,7 @@ endif default: all -all: hello hello++ hellof jacobi thr_hello +all: hello hello++ hellof jacobi thr_hello RCCE_minimum hello++: hello++.o @echo [LD] $@ @@ -84,13 +84,20 @@ thr_hello: thr_hello.o $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym +RCCE_minimum: RCCE_minimum.o + @echo [LD] $@ + $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym + $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ + $Qchmod a-x $@.sym + clean: @echo Cleaning tests - $Q$(RM) hello hello++ hellof jacobi thr_hello *.sym *.o *~ + $Q$(RM) hello hello++ hellof jacobi thr_hello RCCE_minimum *.sym *.o *~ veryclean: @echo Propper cleaning tests - $Q$(RM) hello hello++ hellof jacobi thr_hello *.sym *.o *~ + $Q$(RM) hello hello++ hellof jacobi thr_hello RCCE_minimum *.sym *.o *~ depend: $Q$(CC_FOR_TARGET) -MM $(CFLAGS_FOR_TARGET) *.c > Makefile.dep diff --git a/hermit/usr/tests/RCCE_minimum.c b/hermit/usr/tests/RCCE_minimum.c new file mode 100644 index 000000000..01c040a2d --- /dev/null +++ b/hermit/usr/tests/RCCE_minimum.c @@ -0,0 +1,507 @@ + +/* + * Copyright 2010 Carsten Clauss, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "RCCE.h" + +#undef _SCCPRAM_PUT_REMOTE_ + +extern t_vcharp RCCE_malloc(size_t); +extern int RCCE_put(t_vcharp, t_vcharp, int, int); +extern int RCCE_get(t_vcharp, t_vcharp, int, int); +extern int RCCE_acquire_lock(int); +extern int RCCE_release_lock(int); + + +#define MAX_STEPS 1000*10120 +#define OCCURRENCE 100 + +#undef _TOKEN_PASSING_ +#undef _MASTER_CORE_ +#undef _MASTER_TREE_ + +#pragma omp thread_private(stamp_t, nuM_ranks, my_arnk, steps) +#pragma omp thread_private(my_token, global_tokens, remote_token) +#pragma omp thread_private(distance, neighbor, val_array) + +typedef long long int stamp_t; + +typedef struct _token_t +{ + stamp_t steps; + int rank; + int exit; +} token_t; + + +int num_ranks; +int my_rank; +stamp_t steps; + +token_t my_token; +token_t *global_tokens; + +int distance = 1; +int neighbor; + +volatile unsigned char val_array[RCCE_LINE_SIZE]; +token_t* remote_token; + +#ifdef _TOKEN_PASSING_ +void stop_and_check() +{ +#ifndef _SCCPRAM_PUT_REMOTE_ + neighbor = RCCE_ue() - distance; + if(neighbor < 0) neighbor = neighbor + RCCE_num_ues(); +#else + neighbor = RCCE_ue() + distance; + if( neighbor > RCCE_num_ues() - 1 ) neighbor = neighbor - RCCE_num_ues(); +#endif + + if(neighbor != RCCE_ue()) + { + // do the token-passing: + while(1) + { +#ifndef _SCCPRAM_PUT_REMOTE_ + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, neighbor); +#else + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, RCCE_ue() ); +#endif + + remote_token = (token_t*)val_array; + + //printf("(%d|%lld) neighbor: %d|%lld / my_token: %d|%lld\n", RCCE_ue(), steps, remote_token->rank, remote_token->steps, my_token.rank, my_token.steps); + + if(remote_token->exit) + { + int current = neighbor; + // my current neighbor is atually finished --> determine a new neighbor: + distance++; + +#ifndef _SCCPRAM_PUT_REMOTE_ + neighbor = RCCE_ue() - distance; + if(neighbor < 0) neighbor = neighbor + RCCE_num_ues(); +#else + neighbor = RCCE_ue() + distance; + if( neighbor > RCCE_num_ues() - 1 ) neighbor = neighbor - RCCE_num_ues(); +#endif + if(neighbor == RCCE_ue()) + { + // there is no other neighbor still running --> go on! + break; + } + else + { + // restart token-passing with new neighbor... + continue; + } + } + + if(remote_token->rank == RCCE_ue()) + { + // my own rank has rounded: + if(remote_token->steps == steps) + { + // go on! + break; + } + else + { + // update my token: + my_token.steps = steps; + my_token.rank = RCCE_ue(); + +#ifndef _SCCPRAM_PUT_REMOTE_ + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); +#else + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, neighbor); +#endif + } + } + else + { + if( (steps < remote_token->steps) || ((steps == remote_token->steps) && (RCCE_ue() < remote_token->rank)) ) + { + // update my token: + my_token.steps = steps; + my_token.rank = RCCE_ue(); + +#ifndef _SCCPRAM_PUT_REMOTE_ + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); +#else + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, neighbor); +#endif + } + else + { + if( (remote_token->rank != my_token.rank) || (remote_token->steps != my_token.steps) ) + { + // forward remote token: + memcpy(&my_token, remote_token, sizeof(token_t)); +#ifndef _SCCPRAM_PUT_REMOTE_ + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); +#else + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, neighbor); +#endif + } + } + } + } + } +} +#else +#if defined(_MASTER_CORE_) || defined(_MASTER_TREE_) +void stop_and_check() +{ + while(1) + { + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, RCCE_ue()); + remote_token = (token_t*)val_array; + + // printf("RANK %d: %lld\n", my_rank, steps); fflush(stdout); sleep(1); + + if(remote_token->exit) break; + } +} +#else +void stop_and_check() +{ + int i; + int winner_rank = my_rank; + stamp_t winner_steps = steps; + + while(1) + { + winner_rank = my_rank; + winner_steps = steps; + + for(i=0; isteps < winner_steps) + { + winner_steps = remote_token->steps; + winner_rank = remote_token->rank; + } + } + + if(winner_rank == my_rank) break; + } +} +#endif +#endif + +#ifdef _MASTER_CORE_ +void one_single_master() +{ + int i, j; + int winner_rank; + int winner_flag; + stamp_t winner_steps; + int count; + + count = 0; + + while(1) + { + winner_flag = 0; + + for(i=0,j=0; isteps < winner_steps) ) + { + if(remote_token->exit == 0) + { + j=1; + winner_steps = remote_token->steps; + winner_rank = remote_token->rank; + winner_flag = 1; + } + } + } + + if(winner_flag) + { + my_token.steps = winner_steps; + my_token.rank = winner_rank; + my_token.exit = 1; + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, winner_rank); + } + + count++; + if(count == 1000) + { + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, num_ranks-1); + remote_token = (token_t*)val_array; + + if(remote_token->exit == num_ranks - 1) break; + + count = 0; + } + } +} +#endif +#ifdef _MASTER_TREE_ +void multiple_masters(int flag) +{ + int i; + int winner_rank; + int winner_flag; + stamp_t winner_steps; + int start_rank; + int num_ranks; + int count; + + if(flag) + { + start_rank = 32 + (my_rank-40) * 2; + num_ranks = 2; + } + else + { + start_rank = (my_rank - 32) * 4; + num_ranks = 4; + } + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); + + count = 0; + + while(1) + { + winner_flag = 0; + + for(i=start_rank; isteps < winner_steps) ) + { + winner_steps = remote_token->steps; + winner_rank = remote_token->rank; + winner_flag = 1; + } + } + + if(winner_flag) + { + my_token.steps = winner_steps; + my_token.rank = winner_rank; + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); + } + + count++; + if(count == 1000) + { + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, 47); + remote_token = (token_t*)val_array; + + if(remote_token->exit >= 32) break; + + count = 0; + } + } +} + +void super_master() +{ + int i; + int winner_rank; + int winner_flag; + stamp_t winner_steps; + int start_rank; + int count; + int old_winner_rank = -1; + stamp_t old_winner_steps = 0; + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); + + while(1) + { + winner_flag = 0; + + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, 44); + remote_token = (token_t*)val_array; + + winner_steps = remote_token->steps; + winner_rank = remote_token->rank; + + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, 45); + remote_token = (token_t*)val_array; + + if(remote_token->steps < winner_steps) + { + winner_steps = remote_token->steps; + winner_rank = remote_token->rank; + } + + if( (winner_steps > old_winner_steps) || ( (winner_steps == old_winner_steps) && (winner_rank != old_winner_rank) ) ) + { + winner_flag = 1; + old_winner_rank = winner_rank; + old_winner_steps = winner_steps; + } + + if( winner_flag && (winner_rank < 32) && (winner_rank % 2 == RCCE_ue() % 2) ) + { + my_token.steps = winner_steps; + my_token.rank = winner_rank; + my_token.exit = 1; + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, winner_rank); + } + + count++; + if(count == 1000) + { + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, 47); + remote_token = (token_t*)val_array; + + if(remote_token->exit >= 32) break; + + count = 0; + } + } +} +#endif + +int RCCE_APP(int argc, char **argv) +{ + int i, j; + double timer; + + RCCE_init(&argc, &argv); + + my_rank = RCCE_ue(); + num_ranks = RCCE_num_ues(); + + srand(my_rank); + + global_tokens = (token_t*)RCCE_malloc(RCCE_LINE_SIZE); + + my_token.steps = 0; + my_token.exit = 0; + my_token.rank = RCCE_ue(); + + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); + + RCCE_barrier(&RCCE_COMM_WORLD); + +#ifdef _TOKEN_PASSING_ + if(my_rank == 0) printf("MINIMUM started with %d procs and TOKEN PASSING ...\n", num_ranks); fflush(stdout); +#else +#ifdef _MASTER_CORE_ + if(my_rank == 0) printf("MINIMUM started with %d procs and MASTER CORE ...\n", num_ranks); fflush(stdout); +#else +#ifdef _MASTER_TREE_ + if(my_rank == 0) printf("MINIMUM started with %d procs and MASTER TREE ...\n", num_ranks); fflush(stdout); +#else + if(my_rank == 0) printf("MINIMUM started with %d procs and GLOBAL VIEW ...\n", num_ranks); fflush(stdout); +#endif +#endif +#endif + + RCCE_barrier(&RCCE_COMM_WORLD); + + timer = RCCE_wtime() - timer; + +#ifdef _MASTER_CORE_ + if(my_rank == RCCE_num_ues()-1) one_single_master(); + else for(steps=0; steps < MAX_STEPS / (num_ranks -1); steps++) +#else +#ifdef _MASTER_TREE_ + if(my_rank >= 32) + { + if(my_rank < 40) multiple_masters(0); + else if(my_rank < 46) multiple_masters(1); + else super_master(); + } + else for(steps=0; steps < MAX_STEPS / 32; steps++) +#else + for(steps=0; steps < MAX_STEPS / num_ranks; steps++) +#endif +#endif + { + if( (rand() % OCCURRENCE) == 0 ) + { + stop_and_check(); + } + + my_token.steps = steps; + my_token.rank = RCCE_ue(); + my_token.exit = 0; + +#ifndef _SCCPRAM_PUT_REMOTE_ + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); +#else + neighbor = RCCE_ue() + distance; + if( neighbor > RCCE_num_ues() - 1 ) neighbor = neighbor - RCCE_num_ues(); + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, neighbor); +#endif + } + +#if defined(_MASTER_CORE_) || defined(_MASTER_TREE_) + RCCE_acquire_lock(num_ranks-1); + RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, num_ranks-1); + remote_token = (token_t*)val_array; + remote_token->exit++; + RCCE_put((t_vcharp)global_tokens, val_array, RCCE_LINE_SIZE, num_ranks-1); + RCCE_release_lock(num_ranks-1); +#ifdef _MASTER_TREE_ + if(my_rank < 32) + { + my_token.steps = steps; + my_token.rank = RCCE_ue(); + my_token.exit = 1; + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); + } +#endif +#else + my_token.steps = steps; + my_token.rank = RCCE_ue(); + my_token.exit = 1; + RCCE_put((t_vcharp)global_tokens, (t_vcharp)&my_token, RCCE_LINE_SIZE, RCCE_ue()); +#endif + + RCCE_barrier(&RCCE_COMM_WORLD); + + timer = RCCE_wtime() - timer; + + //printf("EXIT: %d at %lld / count: %d\n", my_rank, steps, remote_token->exit); fflush(stdout); + + if(my_rank == 0) printf("MINIMUM finished after %1.3lf sec.\n", timer); fflush(stdout); + + RCCE_finalize(); + + + return 0; +} +