DynProgr_PPU.c

Go to the documentation of this file.
00001 
00005 /*
00006  * Copyright (c) 2007-2008 ETH Zürich, Institute of Computational Science
00007  *
00008  * Permission is hereby granted, free of charge, to any person
00009  * obtaining a copy of this software and associated documentation
00010  * files (the "Software"), to deal in the Software without
00011  * restriction, including without limitation the rights to use,
00012  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00013  * copies of the Software, and to permit persons to whom the
00014  * Software is furnished to do so, subject to the following
00015  * conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be
00018  * included in all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00022  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00024  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00025  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00026  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00027  * OTHER DEALINGS IN THE SOFTWARE.
00028  */
00029 
00030 #include <stdio.h>
00031 #include <malloc.h>
00032 #ifdef MAIL
00033 #include <libspe.h>
00034 #include <sched.h>
00035 #else
00036 #include <libspe2.h>
00037 #endif
00038 #include <sys/wait.h>
00039 #include <sys/types.h>
00040 #include <errno.h>
00041 #include "DynProgr_SPE.h"
00042 #include <string.h>
00043 #include <stdbool.h>
00044 #include <ctype.h>
00045 #include <limits.h>
00046 #include <time.h>
00047 #include <math.h>
00048 #include <float.h>
00049 #include <assert.h>
00050 
00051 #include "debug.h"
00052 #include "swps3.h"
00053 #include "matrix.h"
00054 #include "DynProgr_scalar.h"
00055 #include "DynProgr_PPU.h"
00056 
00057 #define MAX(a,b) (a>b?a:b)
00058 #define MIN(a,b) (a<b?a:b)
00059 
00060 extern spe_program_handle_t spe_dynprogr_handle;
00061 
00062 #ifdef MAIL
00063 static spe_gid_t getSpeGid(){
00064         static spe_gid_t gid = 0;
00065         if (gid == 0){
00066                 gid = spe_create_group(SCHED_RR, 1, 1);
00067                 if (gid <= 0)
00068                         error("PPU:Creating new group failed");
00069         }
00070         return gid;
00071 }
00073 static speid_t getSpeId(){
00074         static speid_t id = 0;
00075         if (!id)
00076                 id = spe_create_thread(getSpeGid(), &spe_dynprogr_handle, NULL, NULL, -1, 0);
00077         return id;
00078 }
00079 
00081 static void writeMailBox( ppu_addr_t addr ){
00082         speid_t spe_id = getSpeId();
00083         spe_write_in_mbox( spe_id, (uint32_t)addr );
00084         spe_write_in_mbox( spe_id, (uint32_t)(addr>>32) );
00085 }
00086 
00088 static int readMailBox(){
00089         struct spe_event e =  {
00090                 .events = SPE_EVENT_MAILBOX,
00091                 .gid = getSpeGid(),
00092     };
00093         if( !spe_get_event(&e, 1, -1) || e.revents !=  SPE_EVENT_MAILBOX ) error("PPU:Waiting for MailBox signal");
00094         return e.data;
00095 }
00096 #else
00097 static spe_context_ptr_t spe_context = NULL;
00098 #endif
00099 
00105 static int submitSPECommand(SPECommand* command) {
00106 #ifdef MAIL
00107         /* Call the SPU Program*/
00108         writeMailBox( (ppu_addr_t)command );
00109         return readMailBox();
00110 #else
00111         if( !spe_context ){
00112                 spe_context = spe_context_create( 0, NULL );
00113                 spe_program_load( spe_context, &spe_dynprogr_handle );
00114         }
00115         
00116         unsigned int entry = SPE_DEFAULT_ENTRY;
00117         return spe_context_run( spe_context, &entry, 0, command, NULL, NULL );
00118         /* spe_context_destroy( spe_context ); */
00119 #endif
00120 }
00121 
00132 static int SPEInit(int dataType, int maxDbLen, Options *options) {
00133         SPECommand command __ALIGNED__;
00134 
00135         command.command = SPE_CMD_INIT;
00136         command.data.INIT.dbMaxLen = maxDbLen;
00137         command.data.INIT.datatype = dataType;
00138         command.data.INIT.fixedDel = options->gapOpen;
00139         command.data.INIT.incDel = options->gapExt;
00140 
00141         return submitSPECommand(&command);
00142 }
00143 
00157 static int SPECreateProfile(const char* query, int queryLen, const void* matrix, double min, double max) {
00158         SPECommand command __ALIGNED__;
00159         assert(((ppu_addr_t)query & 0xf) == 0 && "query not aligned to 16 bytes");
00160         assert(((ppu_addr_t)matrix & 0xf) == 0 && "matrix not aligned to 16 bytes");
00161 
00162         command.command = SPE_CMD_CREATE_PROFILE;
00163         command.data.CREATE_PROFILE.query.addr = (ppu_addr_t)query;
00164         command.data.CREATE_PROFILE.query.len = queryLen;
00165         command.data.CREATE_PROFILE.matrix.addr = (ppu_addr_t)matrix;
00166         command.data.CREATE_PROFILE.matrix.min = min;
00167         command.data.CREATE_PROFILE.matrix.max = max;
00168 
00169         return submitSPECommand(&command);
00170 }
00171 
00172 static int SPEGetProfile(const SPEProfile *profile) {
00173         SPECommand command __ALIGNED__;
00174         command.command = SPE_CMD_GET_PROFILE;
00175 
00176         assert(((ppu_addr_t)profile->addr & 0xf) == 0 && "profile not aligned to 16 bytes");
00177         memcpy(&command.data.GET_PROFILE.profile, profile, sizeof(*profile));
00178 
00179         return submitSPECommand(&command);
00180 }
00181 
00182 static int SPEPutProfile(void *profile, int *blockSize) {
00183         int ret;
00184         SPECommand command __ALIGNED__;
00185         assert(((ppu_addr_t)profile & 0xf) == 0 && "profile not aligned to 16 byte");
00186 
00187         command.command = SPE_CMD_PUT_PROFILE;
00188         command.data.PUT_PROFILE.blockSize = 0;
00189         command.data.PUT_PROFILE.addr = (ppu_addr_t)profile;
00190 
00191         ret =  submitSPECommand(&command);
00192 
00193         /* write back result */
00194         *blockSize = command.data.PUT_PROFILE.blockSize;
00195 
00196         return ret;
00197 }
00198 
00199 static int SPEAlign(const char *db, int dbLen, double *result) {
00200         int ret;
00201         SPECommand command __ALIGNED__;
00202         assert(((ppu_addr_t)db & 0xf) == 0 && "db sequence not aligned to 16 byte");
00203 
00204         command.command = SPE_CMD_ALIGN;
00205         command.data.ALIGN.result = -1;
00206         command.data.ALIGN.db.len = dbLen;
00207         command.data.ALIGN.db.addr = (ppu_addr_t)db;
00208 
00209         ret =  submitSPECommand(&command);
00210 
00211         /* write back result */
00212         *result = command.data.ALIGN.result;
00213 
00214         return ret;
00215 }
00216 
00217 EXPORT double swps3_alignmentByteSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00218         int i, ret;
00219         double min, max, maxScore;
00220 
00221         ret = SPEInit(SPE_DATA_INT8, dbLen, options);
00222         if(ret != 0) error("error in SPEInit");
00223 
00224         /* Setup the DayMatrix */
00225         max = MAX(options->gapExt,options->gapOpen);
00226         min = MIN(options->gapExt,options->gapOpen);
00227         for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00228                 if(max < matrix[i]) max = matrix[i];
00229                 if(min > matrix[i]) min = matrix[i];
00230         }
00231         ret =  SPECreateProfile(query, queryLen, matrix, min, max);
00232         if(ret != 0) error("error in SPECreateProfile");
00233 
00234         ret = SPEAlign(db, dbLen, &maxScore);
00235         if(ret != 0) error("error in SPEAlign");
00236 
00237         /* If something failed use the ppu version */
00238         if( ret != 0 || maxScore == -1 ){
00239                 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00240                 warning( "sequence too long for SPE program, using PPU fallback\n" );
00241                 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00242                 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00243         }
00244         return maxScore;
00245 }
00246 
00247 EXPORT double swps3_alignmentShortSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00248         int i, ret;
00249         double max, min, maxScore;
00250         int16_t simi[MATRIX_DIM*MATRIX_DIM] __ALIGNED__;
00251 
00252         ret = SPEInit(SPE_DATA_INT16, dbLen, options);
00253         if(ret != 0) error("error in SPEInit");
00254         
00255         /* Setup the DayMatrix */
00256         max = MAX(options->gapExt,options->gapOpen);
00257         min = MIN(options->gapExt,options->gapOpen);
00258         for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00259                 if(max < matrix[i]) max = matrix[i];
00260                 if(min > matrix[i]) min = matrix[i];
00261                 simi[i] = matrix[i];
00262         }
00263         ret =  SPECreateProfile(query, queryLen, simi, min, max);
00264         if(ret != 0) error("error in SPECreateProfile");
00265 
00266         ret = SPEAlign(db, dbLen, &maxScore);
00267         if(ret != 0) error("error in SPEAlign");
00268 
00269         /* If something failed use the ppu version */
00270         if( ret != 0 || maxScore == -1 ){
00271                 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00272                 warning( "sequence too long for SPE program, using PPU fallback\n" );
00273                 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00274                 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00275         }
00276         return maxScore;
00277 }
00278 
00279 EXPORT double swps3_alignmentFloatSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00280         int i, ret;
00281         double max, min, maxScore;
00282         float simi[MATRIX_DIM*MATRIX_DIM] __ALIGNED__;
00283 
00284         ret = SPEInit(SPE_DATA_FLOAT, dbLen, options);
00285         if(ret != 0) error("error in SPEInit");
00286         
00287         /* Setup the DayMatrix */
00288         max = MAX(options->gapExt,options->gapOpen);
00289         min = MIN(options->gapExt,options->gapOpen);
00290         for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00291                 if(max < matrix[i]) max = matrix[i];
00292                 if(min > matrix[i]) min = matrix[i];
00293                 simi[i] = (float)matrix[i];
00294         }
00295         ret =  SPECreateProfile(query, queryLen, simi, min, max);
00296         if(ret != 0) error("error in SPECreateProfile");
00297 
00298         ret = SPEAlign(db, dbLen, &maxScore);
00299         if(ret != 0) error("error in SPEAlign");
00300 
00301         /* If something failed use the ppu version */
00302         if( ret != 0 || maxScore == -1 ){
00303                 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00304                 warning( "sequence too long for SPE program, using PPU fallback\n" );
00305                 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00306                 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00307         }
00308         return maxScore;
00309 }
00310 
00314 EXPORT double swps3_alignmentProfileSPE( const char * db, int dbLen )
00315 {
00316         double maxScore;
00317         int ret;
00318 
00319         ret = SPEAlign(db, dbLen, &maxScore);
00320         if(ret != 0) maxScore = -1;
00321 
00322         return maxScore;
00323 }
00324 
00325 EXPORT void swps3_loadProfileByte(SPEProfile *profile, int maxDbLen, Options *options)
00326 {
00327         int ret;
00328 
00329         ret = SPEInit(SPE_DATA_INT8, maxDbLen, options);
00330         if(ret != 0) error("error in SPEInit");
00331 
00332         ret = SPEGetProfile(profile);
00333         if(ret != 0) error("error in SPEGetProfile");
00334 }
00335 
00336 EXPORT void swps3_loadProfileShort(SPEProfile *profile, int maxDbLen, Options *options)
00337 {
00338         int ret;
00339 
00340         ret = SPEInit(SPE_DATA_INT16, maxDbLen, options);
00341         if(ret != 0) error("error in SPEInit");
00342 
00343         ret = SPEGetProfile(profile);
00344         if(ret != 0) error("error in SPEGetProfile");
00345 }
00346 
00347 EXPORT void swps3_loadProfileFloat(SPEProfile *profile, int maxDbLen, Options *options)
00348 {
00349         int ret;
00350 
00351         ret = SPEInit(SPE_DATA_FLOAT, maxDbLen, options);
00352         if(ret != 0) error("error in SPEInit");
00353 
00354         ret = SPEGetProfile(profile);
00355         if(ret != 0) error("error in SPEGetProfile");
00356 }
00357 
00358 #define T int8_t
00359 EXPORT SPEProfile * swps3_createProfileBytePPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00360 {
00361 #include "DynProgr_PPU_profile.inc"
00362 }
00363 #undef T
00364 
00365 #define T int16_t
00366 EXPORT SPEProfile * swps3_createProfileShortPPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00367 {
00368 #include "DynProgr_PPU_profile.inc"
00369 }
00370 #undef T
00371 
00372 #define T float
00373 EXPORT SPEProfile * swps3_createProfileFloatPPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00374 {
00375 #include "DynProgr_PPU_profile.inc"
00376 }
00377 #undef T
00378 
00379 EXPORT void swps3_freeProfilePPU(SPEProfile *profile) {
00380         free((void*)profile->addr);
00381         free(profile);
00382 }
00383 

Generated on Thu Jun 5 12:44:37 2008 for swps3 by  doxygen 1.5.4