Menu

Tree [r7] /
 History

HTTPS access


File Date Author Commit
 examples 2009-06-25 gshi [r6] disable NUMA by default
 ppu 2009-06-16 gshi [r4] Applying the patch from gcst to fix some hardco...
 spu 2009-06-08 gshi [r1] initial code drop
 Makefile 2009-06-08 gshi [r1] initial code drop
 README 2009-06-25 gshi [r7] update the README, added some explanation to th...
 make_options 2009-06-16 gshi [r4] Applying the patch from gcst to fix some hardco...

Read Me

#  Illinois Open Source License
#  
#  University of Illinois/NCSA
#  Open Source License
#  
#  Copyright © 2009,    University of Illinois.  All rights reserved.
#  
#  Developed by:
#  
#  Innovative Systems Lab  
#  National Center for Supercomputing Applications  
#  http://www.ncsa.uiuc.edu/AboutUs/Directorates/ISL.html
#  
#  Permission is hereby granted, free of charge, to any person obtaining a copy of 
#  this software and associated documentation files (the "Software"), to deal with 
#  the Software without restriction, including without limitation the rights to use,
#  copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 
#  Software, and to permit persons to whom the Software is furnished to do so, subject
#  to the following conditions:
#  
#  * Redistributions of source code must retain the above copyright notice, this list 
#  of conditions and the following disclaimers.
#
#  * Redistributions in binary form must reproduce the above copyright notice, this list
#  of conditions and the following disclaimers in the documentation and/or other materials
#  provided with the distribution.
#
#  * Neither the names of the Innovative Systems Lab, the National Center for Supercomputing
#  Applications, nor the names of its contributors may be used to endorse or promote products
#  derived from this Software without specific prior written permission.
#  
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
#  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
#  PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE
#  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 
#  OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
#  DEALINGS WITH THE SOFTWARE.
#


This library is build upon libspe2 from IBM Cell SDK. The motivation for the library
is to hide the tedious context/pthread creation, mailbox/signal/interrupt mailbox communication
in order to start jobs in SPUs and give a clean interface to the programmer. 

Compiling the library
	
	After downloading and untaring the library, you can do "make" in the root directory and it should compile.
	Do a "make install" will install the necessary head files and libraries into your home directory: ${HOME}/celltask
	You can change where you want to install by editting the Makefiles in 

---------------------------------------------------------------------------------------
Examples:
There are two examples in the example directories using the library.

1. examples/helloworld

The simple program to show how to register a function, construct a task and retrive the parameters in the spu program

2. /examples/matmul

This program is a more complicated example showing how to do an array of 4x4 matrix multiplication, using double buffering.


---------------------------------------------------------------------------------------
A quick look of the APIs

PPE:
            int ppu_task_init(int argc, char **argv, spe_program_handle_t spe_main);
            int ppu_task_run(volatile task_t * task);
            int ppu_task_wait(void);
            void ppu_task_debug_level_set(int);
            int  ppu_task_debug_level_get(void);
            extern int ppu_task_spe_num_get();
            extern int ppu_task_spe_num_set(int);
            int ppu_task_spu_run(volatile task_t* task, int sperank);
            int ppu_task_spu_wait(void);
            void ppu_task_spu_waiton(int);
            void ppu_task_spu_waitall(void);
            void ppu_task_spu_time_reset(void);
            double ppu_task_spu_time_get(void);
            void ppu_task_physid_as_rank_set();
            void ppu_task_physid_as_rank_reset();
SPE:
	int     spu_task_size_get(void);
	int     spu_task_rank_get(void);
	int     spu_task_init(unsigned long long);
	int     spu_task_run(void);
	int     spu_task_register(dotask_t,int);
	char*   spu_task_ls_get(int);
	void    spu_task_debug_level_set(int);
	int     send_msg_to_mailbox(int rank, int value);
	int     recv_msg_from_mailbox(void);
	void    spu_barrier(void);



	What you care most are

	ppu_task_spe_num_set(), //Set the number of SPEs to use. This one should be called before youc call the ppu_task_init(). 
	ppu_task_init(), //which will initialize the data structures, create threads, run spe context and assign each spe a rank
	ppu_task_run(), //This function launches a function call, blocking, and it uses all spes, i.e each spe get the same task struct
			//and they are to figure which part of work they should according to their rank.


	spu_task_init(), // init the task library in spe
	spu_task_register(), //this one register a task ( a function) to an index( integer)
				// this function can be called multiple time to register different tasks
	spu_task_run(), 	//blocking function, infinite loop, unless one task function returns non-zero indicating error
	

Here is a simple example on how to use libtask library (PPE code)

	extern spe_program_handle_t spu_main;

	compute_task_t task __attribute__ ((aligned (128)));

	int
	main(int argc, char** argv)
	{
	    int n = 1;

	    ppu_task_spe_num_set(n);
	    ppu_task_debug_level_set(0);

	    if (ppu_task_init(0, NULL, spu_main) < 0){
	        printf("Init failed\n");
	        return -1;
	    }

	    task.common.cmd = COMPUTE_TASK;
	    task.common.size = sizeof(task);
	    task.a = 1;
	    task.b = 2;
	    ppu_task_run((task_t*)&task);

	    return 0;
	}


I uses the integer a and b to demonstrate how variables can be transfered to SPEs.  The function ppu_task_debug_level_set() is
to set the debug level, the default is 0 (no debug output); if it is set to nonzero, there will be verbose output.
The task structure is customized, but the first 8 bytes must be task_t,

	typedef struct compute_task_s{
    		task_t common;
        	int a;
        	int b;
	}compute_task_t;



The spe code is like the following


	int
	main(unsigned long long spu_id, unsigned long long parm)
	{
    		int rank;
    		int rc;

    		spu_task_debug_level_set(0);
   		spu_task_init(parm);
    		spu_task_register(do_compute_db, COMPUTE_TASK);
    		spu_task_run();
    		return 0;
	}

where all functions are self-explanary. The do_compute_db is a function

	int
	do_compute_db(task_t* _task)
	{
    		compute_task_t* task = (compute_task_t*)_task;
	
    		spu_log("got paramters: a=%d, b=%d\n", task->a, task->b);
    		return 0;
	}


The whole example program are available in examples/helloworld/
	
Therefore, the program can focus on putting whatever paramers necessary for computation into the compute_task_t structure, 
assign the values to them in ppe, and retrive the values in spe. Each spe should do part of the whole computation according to 
its rank. You can get spe's rank from spu_task_rank_get();


There is another mode where each spes works its own, in that case, the ppe side should call the functions:
	ppu_task_spu_*

I will write more about that if there is need to.


Qestions/suggestions? Please send emails to gshi@ncsa.uiuc.edu





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.