1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00
libhermit/usr/tests/RCCE_minimum.c
2016-12-03 00:43:49 +01:00

507 lines
12 KiB
C

/*
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#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; i<num_ranks; i++)
{
RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, i);
remote_token = (token_t*)val_array;
if(remote_token->steps < 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; i<num_ranks - 1; i++)
{
RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, i);
remote_token = (token_t*)val_array;
if( (!j) || (remote_token->steps < 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; i<start_rank + num_ranks; i++)
{
RCCE_get(val_array, (t_vcharp)global_tokens, RCCE_LINE_SIZE, i);
remote_token = (token_t*)val_array;
if( (i==start_rank) || (remote_token->steps < 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;
}