diff --git a/src/aig/gia/giaTranStoch.c b/src/aig/gia/giaTranStoch.c index 78dc1424d..efc358dde 100644 --- a/src/aig/gia/giaTranStoch.c +++ b/src/aig/gia/giaTranStoch.c @@ -29,6 +29,17 @@ #include #include +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#include +#endif + +#endif + ABC_NAMESPACE_IMPL_START extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); @@ -69,22 +80,60 @@ void Gia_ManTranStochFx( Abc_Ntk_t * pNtk ) { Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); Abc_NtkFxuFreeInfo( p ); } +Gia_Man_t * Gia_ManTranStochRefactor( Gia_Man_t * pGia ) { + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pTemp; + Dar_RefPar_t Pars, * pPars = &Pars; + Dar_ManDefaultRefParams( pPars ); + pPars->fUseZeros = 1; + pAig = Gia_ManToAig( pGia, 0 ); + Dar_ManRefactor( pAig, pPars ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + pNew = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pNew; +} struct Gia_ManTranStochParam { + Gia_Man_t * pStart; int nSeed; int nHops; int nRestarts; int nSeedBase; - int fCspf; + int fMspf; int fMerge; int fResetHop; + int fZeroCostHop; + int fRefactor; int fTruth; int fNewLine; Gia_Man_t * pExdc; int nVerbose; + +#ifdef ABC_USE_PTHREADS + int nSp; + int nIte; + Gia_Man_t * pRes; + int fWorking; + pthread_mutex_t * mutex; +#endif }; typedef struct Gia_ManTranStochParam Gia_ManTranStochParam; + +void Gia_ManTranStochLock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_lock( p->mutex ); +#endif +} +void Gia_ManTranStochUnlock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_unlock( p->mutex ); +#endif +} Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { Gia_Man_t * pGia, * pNew; @@ -93,14 +142,22 @@ Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) do { n = Gia_ManAndNum( pGia ); if ( p->fTruth ) - pNew = Gia_ManTransductionTt( pGia, (p->fMerge? 8: 7), !p->fCspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + pNew = Gia_ManTransductionTt( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); else - pNew = Gia_ManTransductionBdd( pGia, (p->fMerge? 8: 7), !p->fCspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); - Gia_ManStop( pGia ); - pGia = pNew; - pNew = Gia_ManCompress2( pGia, 1, 0 ); + pNew = Gia_ManTransductionBdd( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); Gia_ManStop( pGia ); pGia = pNew; + if ( p->fRefactor ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNew = Gia_ManCompress2( pGia, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pGia = pNew; + } if ( p->nVerbose ) printf( "* ite %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); i++; @@ -108,11 +165,11 @@ Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) return pGia; } -Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { - int i, n = Gia_ManAndNum( pOld ); +Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); Gia_Man_t * pGia, * pBest, * pNew; Abc_Ntk_t * pNtk, * pNtkRes; - pGia = Gia_ManDup( pOld ); + pGia = Gia_ManDup( p->pStart ); pBest = Gia_ManDup( pGia ); for ( i = 0; 1; i++ ) { pNew = Gia_ManTranStochOpt1( p, pGia ); @@ -127,17 +184,27 @@ Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) } if ( i == p->nHops ) break; - pNtk = Gia_ManTranStochPut( pGia ); - Gia_ManStop( pGia ); - pNtkRes = Gia_ManTranStochIf( pNtk ); - Abc_NtkDelete( pNtk ); - pNtk = pNtkRes; - Gia_ManTranStochMfs2( pNtk ); - pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); - Abc_NtkDelete( pNtk ); - pNtk = pNtkRes; - pGia = Gia_ManTranStochGet( pNtk ); - Abc_NtkDelete( pNtk ); + if ( p->fZeroCostHop ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNtk = Gia_ManTranStochPut( pGia ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pNtkRes = Gia_ManTranStochIf( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Gia_ManTranStochMfs2( pNtk ); + Gia_ManTranStochLock( p ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pGia = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + } if ( p->nVerbose ) printf( "* hop %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); } @@ -145,13 +212,13 @@ Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) return pBest; } -Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { - int i, n = Gia_ManAndNum( pOld ); +Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); Gia_Man_t * pBest, * pNew; - pBest = Gia_ManDup( pOld ); + pBest = Gia_ManDup( p->pStart ); for ( i = 0; i <= p->nRestarts; i++ ) { p->nSeed = 1234 * (i + p->nSeedBase); - pNew = Gia_ManTranStochOpt2( p, pOld ); + pNew = Gia_ManTranStochOpt2( p ); if ( p->nRestarts && p->nVerbose ) printf( "* res %2d : #nodes = %5d\n", i, Gia_ManAndNum( pNew ) ); if ( n > Gia_ManAndNum( pNew ) ) { @@ -165,7 +232,28 @@ Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) return pBest; } -Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fCspf, int fMerge, int fResetHop, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nVerbose ) { +#ifdef ABC_USE_PTHREADS +void * Gia_ManTranStochWorkerThread( void * pArg ) { + Gia_ManTranStochParam * p = (Gia_ManTranStochParam *)pArg; + volatile int * pPlace = &p->fWorking; + while ( 1 ) { + while ( *pPlace == 0 ); + assert( p->fWorking ); + if ( p->pStart == NULL ) { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + p->nSeed = 1234 * (p->nIte + p->nSeedBase); + p->pRes = Gia_ManTranStochOpt2( p ); + p->fWorking = 0; + } + assert( 0 ); + return NULL; +} +#endif + +Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ) { int i, j = 0; Gia_Man_t * pNew, * pBest, * pStart; Abc_Ntk_t * pNtk, * pNtkRes; Vec_Ptr_t * vpStarts; @@ -173,13 +261,18 @@ Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nS p->nRestarts = nRestarts; p->nHops = nHops; p->nSeedBase = nSeedBase; - p->fCspf = fCspf; + p->fMspf = fMspf; p->fMerge = fMerge; p->fResetHop = fResetHop; + p->fZeroCostHop = fZeroCostHop; + p->fRefactor = fRefactor; p->fTruth = fTruth; p->fNewLine = fNewLine; p->pExdc = pExdc; p->nVerbose = nVerbose; +#ifdef ABC_USE_PTHREADS + p->fWorking = 0; +#endif // setup start points vpStarts = Vec_PtrAlloc( 4 ); Vec_PtrPush( vpStarts, Gia_ManDup( pGia ) ); @@ -232,21 +325,97 @@ Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nS } // optimize pBest = Gia_ManDup( pGia ); - Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) { - if ( p->nVerbose ) - printf( "*begin starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pStart ) ); - pNew = Gia_ManTranStochOpt3( p, pStart ); - if ( p->nVerbose ) - printf( "*end starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pNew ) ); - if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( pNew ) ) { - Gia_ManStop( pBest ); - pBest = pNew; - } else { - Gia_ManStop( pNew ); + if ( nThreads == 1 ) { + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) { + if ( p->nVerbose ) + printf( "*begin starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pStart ) ); + p->pStart = pStart; + pNew = Gia_ManTranStochOpt3( p ); + if ( p->nVerbose ) + printf( "*end starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pNew ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( pNew ) ) { + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + Gia_ManStop( pStart ); } - Gia_ManStop( pStart ); + } else { +#ifdef ABC_USE_PTHREADS + static pthread_mutex_t mutex; + int k, status, nIte, fAssigned, fWorking; + Gia_ManTranStochParam ThData[100]; + pthread_t WorkerThread[100]; + p->pRes = NULL; + p->mutex = &mutex; + if ( p->nVerbose ) + p->nVerbose--; + for ( i = 0; i < nThreads; i++ ) { + ThData[i] = *p; + status = pthread_create( WorkerThread + i, NULL, Gia_ManTranStochWorkerThread, (void *)(ThData + i) ); + assert( status == 0 ); + } + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, k ) { + for ( nIte = 0; nIte <= p->nRestarts; nIte++ ) { + fAssigned = 0; + while ( !fAssigned ) { + for ( i = 0; i < nThreads; i++ ) { + if ( ThData[i].fWorking ) + continue; + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + ThData[i].nSp = j + k; + ThData[i].nIte = nIte; + ThData[i].pStart = pStart; + ThData[i].fWorking = 1; + fAssigned = 1; + break; + } + } + } + } + fWorking = 1; + while ( fWorking ) { + fWorking = 0; + for ( i = 0; i < nThreads; i++ ) { + if( ThData[i].fWorking ) { + fWorking = 1; + continue; + } + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + } + } + for ( i = 0; i < nThreads; i++ ) { + ThData[i].pStart = NULL; + ThData[i].fWorking = 1; + } +#else + printf( "ERROR: pthread is off" ); +#endif + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) + Gia_ManStop( pStart ); } - if ( p->nVerbose ) + if ( nVerbose ) printf( "best: %d\n", Gia_ManAndNum( pBest ) ); Vec_PtrFree( vpStarts ); return pBest; diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index cb403e315..732b60c8f 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -42755,11 +42755,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fCspf, int fMerge, int fResetHop, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nVerbose ); + extern Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ); Gia_Man_t * pTemp, * pExdc = NULL; - int c, nRestarts = 0, nHops = 10, nSeedBase = 0, fCspf = 0, fMerge = 1, fResetHop = 1, fTruth = 0, fSingle = 0, fOriginalOnly = 0, fNewLine = 0, nVerbose = 1; + int c, nRestarts = 0, nHops = 10, nSeedBase = 0, fMspf = 1, fMerge = 1, fResetHop = 1, fZeroCostHop = 0, fRefactor = 0, fTruth = 0, fSingle = 0, fOriginalOnly = 0, fNewLine = 0, nThreads = 1, nVerbose = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NMRVcmrtsonh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NMRPVmgrzftsonh" ) ) != EOF ) { switch ( c ) { @@ -42790,6 +42790,15 @@ int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) nSeedBase = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nThreads = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'V': if ( globalUtilOptind >= argc ) { @@ -42799,15 +42808,21 @@ int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) nVerbose = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'c': - fCspf ^= 1; - break; case 'm': + fMspf ^= 1; + break; + case 'g': fMerge ^= 1; break; case 'r': fResetHop ^= 1; break; + case 'z': + fZeroCostHop ^= 1; + break; + case 'f': + fRefactor ^= 1; + break; case 't': fTruth ^= 1; break; @@ -42852,22 +42867,25 @@ int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - pTemp = Gia_ManTranStoch( pAbc->pGia, nRestarts, nHops, nSeedBase, fCspf, fMerge, fResetHop, fTruth, fSingle, fOriginalOnly, fNewLine, pExdc, nVerbose ); + pTemp = Gia_ManTranStoch( pAbc->pGia, nRestarts, nHops, nSeedBase, fMspf, fMerge, fResetHop, fZeroCostHop, fRefactor, fTruth, fSingle, fOriginalOnly, fNewLine, pExdc, nThreads, nVerbose ); if ( pExdc != NULL ) Gia_ManStop( pExdc ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &transtoch [-NMRV num] [-cmrtsonh] \n" ); + Abc_Print( -2, "usage: &transtoch [-NMRPV num] [-mgrzftsonh] \n" ); Abc_Print( -2, "\t iterates transduction with randomized parameters\n" ); Abc_Print( -2, "\t-N num : number of restarts [default = %d]\n", nRestarts ); Abc_Print( -2, "\t-M num : number of hops (if; mfs2; strash) [default = %d]\n", nHops ); Abc_Print( -2, "\t-R num : random seed [default = %d]\n", nSeedBase ); + Abc_Print( -2, "\t-P num : number of threads [default = %d]\n", nThreads ); Abc_Print( -2, "\t-V num : verbosity level [default = %d]\n", nVerbose); - Abc_Print( -2, "\t-c : toggles using CSPF instead of MSPF [default = %s]\n", fCspf? "yes": "no" ); - Abc_Print( -2, "\t-m : toggles using ResubShared [default = %s]\n", fMerge? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles using MSPF instead of CSPF [default = %s]\n", fMspf? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles using ResubShared [default = %s]\n", fMerge? "yes": "no" ); Abc_Print( -2, "\t-r : toggles resetting hop count when new minimum is found [default = %s]\n", fResetHop? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles using \"drf -z\" instead of \"if;mfs2;st\" for hop [default = %s]\n", fZeroCostHop? "yes": "no" ); + Abc_Print( -2, "\t-f : toggles using \"drf -z\" instead of \"&dc2\" for ite [default = %s]\n", fRefactor? "yes": "no" ); Abc_Print( -2, "\t-t : toggles using truth table instead of BDD [default = %s]\n", fTruth? "yes": "no" ); Abc_Print( -2, "\t-s : toggles starting from the smallest starting point [default = %s]\n", fSingle? "yes": "no" ); Abc_Print( -2, "\t-o : toggles starting from the given AIG [default = %s]\n", fOriginalOnly? "yes": "no" );