int main ( int argc, char * argv[]) { SCOTCH_Num vertnbr; /* Number of vertices */ SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Ordering ordedat; /* Graph ordering */ SCOTCH_Num * permtab; /* Permutation array */ SCOTCH_Strat stradat; /* Ordering strategy */ SCOTCH_Num straval; char * straptr; int flagval; Clock runtime[2]; /* Timing variables */ int i, j; errorProg ("gord"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; /* Default behavior */ straval = 0; /* No strategy flags */ straptr = NULL; SCOTCH_stratInit (&stradat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; default : errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); } } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* Output separator mapping */ case 'm' : flagval |= C_FLAGMAPOUT; if (argv[i][2] != '\0') C_filenamemapout = &argv[i][2]; break; case 'O' : /* Ordering strategy */ case 'o' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratGraphOrder (&stradat, straptr); break; case 'T' : /* Output separator tree */ case 't' : flagval |= C_FLAGTREOUT; if (argv[i][2] != '\0') C_filenametreout = &argv[i][2]; break; case 'V' : fprintf (stderr, "gord, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 2); /* Read source graph */ SCOTCH_graphSize (&grafdat, &vertnbr, NULL); /* Get graph characteristics */ if (straval != 0) { if (straptr != NULL) errorPrint ("main: options '-c' and '-o' are exclusive"); SCOTCH_stratGraphOrderBuild (&stradat, straval, 0, 0.2); } clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); clockStart (&runtime[1]); if ((permtab = (SCOTCH_Num *) memAlloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, NULL, NULL, NULL, NULL); /* Create ordering */ SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat); /* Perform ordering */ clockStop (&runtime[1]); /* Get ordering time */ #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) return (1); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[0]); SCOTCH_graphOrderSave (&grafdat, &ordedat, C_filepntrordout); /* Write ordering */ if (flagval & C_FLAGMAPOUT) /* If mapping wanted */ SCOTCH_graphOrderSaveMap (&grafdat, &ordedat, C_filepntrmapout); /* Write mapping */ if (flagval & C_FLAGTREOUT) /* If separator tree wanted */ SCOTCH_graphOrderSaveTree (&grafdat, &ordedat, C_filepntrtreout); /* Write tree */ clockStop (&runtime[0]); /* Get output time */ if (flagval & C_FLAGVERBSTR) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if (flagval & C_FLAGVERBTIM) { fprintf (C_filepntrlogout, "T\tOrder\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", (double) clockVal (&runtime[1]), (double) clockVal (&runtime[0]), (double) clockVal (&runtime[0]) + (double) clockVal (&runtime[1])); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphOrderExit (&grafdat, &ordedat); SCOTCH_stratExit (&stradat); SCOTCH_graphExit (&grafdat); memFree (permtab); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); }
bool ScotchSplitter(unsigned dim, const int* ptRows, const int* indCols, unsigned& nbMaxLevels, unsigned minSize, int* loc2glob, int* glob2loc, int& nbDoms, int*& ptOnDomains, int*& sizeOfDomains, bool checkData, const bool verbose, FILE *fp) { int ierr; // check consistency between Scotch and Dissection library CHECK(sizeof(int) == sizeof(SCOTCH_Num), "Incompatible integer representation between Scotch and Dissection"); if (verbose) { int vers, rela, patc; SCOTCH_version(&vers, &rela, &patc); diss_printf(verbose, fp, "%s %d : Soctch version : %d.%d.%d\n", __FILE__, __LINE__, vers, rela, patc); } // Allocate and initialize the Scotch graph SCOTCH_Graph ptGraph; ierr = SCOTCH_graphInit(&ptGraph); CHECK(ierr==0,"Fail initializing Scotch graph"); // TRACE("Building Scotch graph\n"); ierr = SCOTCH_graphBuild(&ptGraph, (SCOTCH_Num)0, // offset, (SCOTCH_Num)dim, (const SCOTCH_Num*)ptRows, (const SCOTCH_Num*)ptRows+1, NULL, NULL, (SCOTCH_Num)ptRows[dim], (const SCOTCH_Num*)indCols, NULL); // if (verbose) { // fprintf(fp, "%s %d : 1 : ptRows = %p indCols = %p\n", // __FILE__, __LINE__, (void *)ptRows, (void *)indCols); // } CHECK(ierr==0,"Scotch graph building failed !"); if (checkData) { //TRACE("Check Scotch graph\n"); ierr = SCOTCH_graphCheck(&ptGraph); if (ierr) { diss_printf(verbose, fp, "Failed the checking of the graph : bad data ?\n"); SCOTCH_graphFree(&ptGraph); return false; } } // Allocate and initialize the strategy wanted for Scotch // TRACE("Initialize strategy for splitting\n"); SCOTCH_Strat ptStrat; ierr = SCOTCH_stratInit(&ptStrat); CHECK(ierr==0, "Failed initializing Scotch strategy structure"); char *str_Strat = new char[1024]; int nbLvls = std::min(unsigned(nbMaxLevels), highestbit(unsigned(dim/minSize))); diss_printf(verbose, fp, "nbLevels = %d\n", nbLvls); sprintf(str_Strat,"c{rat=0.7,cpr=n{sep=/((levl<%d)|(vert>%d))?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=f{cmin=%d,cmax=%d,frat=0.05},ose=s},unc=n{sep=/(levl<%d)?(m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}})|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=f{cmin=%d,cmax=%d,frat=0.05},ose=s}}", nbLvls-1,2*minSize-1,minSize,dim,nbLvls-1,minSize,dim); // DBG_PRINT("Strategy string : %s\n", str_Strat); ierr = SCOTCH_stratGraphOrder(&ptStrat, str_Strat); delete [] str_Strat; CHECK(ierr==0, "Failed build graph ordering strategy for Scotch"); // Ordering with nested bisection : // TRACE("Split the graph\n"); int* rangtab = new int[dim+1]; int* treetab = new int[dim]; int nbSplitDoms; bool repeat = true; int lastCompleteLevel; int *levels, *nbDomsPerLevels; SCOTCH_randomReset(); while (repeat) { ierr = SCOTCH_graphOrder(&ptGraph, &ptStrat, (SCOTCH_Num*)loc2glob, (SCOTCH_Num*)glob2loc, (SCOTCH_Num*)&nbSplitDoms, (SCOTCH_Num*)rangtab, (SCOTCH_Num*)treetab); if (ierr) { diss_printf(verbose, fp, "Failed reordering sparse matrix graph !\n"); SCOTCH_stratExit(&ptStrat); SCOTCH_graphFree(&ptGraph); return false; } levels = new int[nbSplitDoms]; // int *nbDomsPerLevels;// = new int[nbLvls]; unsigned nbLvlsScotch= compLevelOfDoms(nbSplitDoms, nbLvls, treetab, levels, nbDomsPerLevels); /** Search last level where number of domains is a power of two */ lastCompleteLevel = 0; while ((lastCompleteLevel<nbLvlsScotch) && ((1<<lastCompleteLevel) == nbDomsPerLevels[lastCompleteLevel]) ) { lastCompleteLevel ++; } lastCompleteLevel = std::min(lastCompleteLevel, nbLvls); nbDoms = (1<<lastCompleteLevel)-1; // Search where start each domain per bisection level // and compute the size of each subdomain : // int indDom = 0; bool flag_size_check = false; for (int i = 0; i < nbSplitDoms; i++) { int sz = 0; while (levels[i]>=lastCompleteLevel) { sz += rangtab[i+1]-rangtab[i]; i++; } if (sz+rangtab[i+1]-rangtab[i] <= TOO_SMALL) { flag_size_check = true; break; } //DBG_PRINT("Domain %d begin at %d\n",indDom+1,begDom); } // loop : i if (!flag_size_check) { repeat = false; break; } else { delete [] levels; delete [] nbDomsPerLevels; } } // while (repeat) ptOnDomains = new int[nbDoms+1]; sizeOfDomains = new int[nbDoms]; memset(sizeOfDomains, 0, nbDoms*sizeof(int)); int* indDomPerLevel = new int[lastCompleteLevel+1]; memset(indDomPerLevel,0,(lastCompleteLevel+1)*sizeof(int)); int begDom = 0; for (int i = 0; i < nbSplitDoms; i++) { int sz = 0; while (levels[i]>=lastCompleteLevel) { sz += rangtab[i+1]-rangtab[i]; i++; } int indDom = (1<<levels[i])-1+indDomPerLevel[levels[i]]; // DBG_PRINT("level %d : current dom = %d\n", levels[i],indDom+1); ptOnDomains[indDom] = begDom; //DBG_PRINT("Domain %d begin at %d\n",indDom+1,begDom); sizeOfDomains[indDom] = sz+rangtab[i+1]-rangtab[i]; //DBG_PRINT("Domain %d size of %d\n",indDom+1,sizeOfDomains[indDom]); begDom += sizeOfDomains[indDom]; indDomPerLevel[levels[i]] += 1; } diss_printf(verbose, fp, "%s %d : indDomPerlevel[lastCompleteLevel] = %d\n", __FILE__, __LINE__, indDomPerLevel[lastCompleteLevel]); ptOnDomains[nbDoms] = dim; nbMaxLevels = lastCompleteLevel; delete [] indDomPerLevel; delete [] nbDomsPerLevels; delete [] levels; delete [] treetab; delete [] rangtab; // Cleaning all Scotch structures : SCOTCH_stratExit(&ptStrat); SCOTCH_graphFree(&ptGraph); return true; }