Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language UPC (Unified Parallel C)

(uses atomic memory operations)

Date:08/09/06
Author:Phil Merkey
URL:www.upc.mtu.edu
Comments:0
Info:http://upcworld.org
Score: (2.77 in 124 votes)
*
 * UPC (Unified Parallel C: www.upcworld.org) by Phil Merkey
 * To run as a C program compile: gcc 99bottles.c
 * To run as a UPC program on a Cray X1 
 *   compile: cc -hupc -hssp 99bottles.c
 *       run: aprun -n <THREADS> ./a.out
 * Other versions of UPC will require an appropriate macro
 * for 'fetch_and_minus'
 */
#include <stdio.h>
#include <time.h>

#define ROUNDS 100
#define VERSE_LEN 132

#if __UPC__

#include <upc.h>
#include <intrinsics.h>
shared long counter;
#define fetch_and_minus(A) _amo_afadd((volatile long *)(A), -1)
shared [] char song[ROUNDS*VERSE_LEN];

#else

#define upc_barrier
#define MYTHREAD 0
#define upc_memput memcpy
long counter;
#define fetch_and_minus(A) serial_fetch_and_add((long *)(A), -1)
char song[ROUNDS*VERSE_LEN];

#endif

main()
{
    int cnt, offset;
    char verse_buf[VERSE_LEN];

    srand48(33*MYTHREAD);
    if(MYTHREAD == 0) counter = ROUNDS-1;
    upc_barrier;

    while(1){
        cnt = fetch_and_minus( &counter );
        if( cnt < 0 )
            break;
        offset = build_verse( cnt , verse_buf );
        upc_memput( &song[offset], verse_buf, VERSE_LEN );
    }
    upc_barrier;
    if(MYTHREAD == 0 )  printf("%s", (char *) song);
}

/*
 * Note that each thread pulls the next available bottle off the wall,
 * takes a random amount of time to complete the task of building 
 * the verse, then writes it into the correct location in the song. 
 * This allows each thread to contribute to the construction of the 
 * song while handling issues of load-balancing and synchronization 
 * in a natural way.
 */

int build_verse(int cnt, char *vrs)
{
    char stash[60];
    struct timespec surfeiting;

    report_stash(1, cnt, stash );
    sprintf(vrs,"\n\n%s on the wall, ", stash);
    report_stash(0, cnt, stash );
    sprintf(vrs+strlen(vrs),"%s.", stash);
    surfeiting.tv_sec = 0;
    surfeiting.tv_nsec = (ROUNDS-cnt)*(lrand48() % 100000);
    nanosleep(&surfeiting, NULL);
    if ( cnt ==  0 ){
        sprintf(vrs+strlen(vrs), "\nGo to the store and buy some more, ");
        report_stash(0, ROUNDS-1, stash );
        sprintf(vrs+strlen(vrs), "%s on the wall.\n", stash);
     } else {
        sprintf(vrs+strlen(vrs), "\nTake one down and pass it around, ");
        report_stash(0, cnt-1, stash );
        sprintf(vrs+strlen(vrs), "%s on the wall.                 ", stash);
    }
    return( (ROUNDS-1-cnt) * VERSE_LEN );
}

report_stash(int cap, int nb, char *stash )
{
    if( nb == 0 )
        sprintf(stash, "%co more bottles of beer", (cap)?'N':'n' );
    else
        sprintf(stash, "%d bottle%s of beer", nb, (nb>1)?"s":"");
}

int serial_fetch_and_add( long *cntr, int val )
{
    int ret;
    ret = *cntr;
    *cntr += val;
    return(ret);
}

Download Source | Write Comment

Alternative Versions

Comments

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: