//-------------------------------------------------------// //---- SetUp -------------------------------------// //-------------------------------------------------------// void SetUp( long int** table, // polyphase merge table int order, int nruns, int runsize, Device* devices[], Device* sources[], Device*& dest ) { int i; long int* initial_dist; // initial distribution long int* dummy_list; // distribution of dummies initial_dist = new long int [order+1]; dummy_list = new long int [order+1]; for (i = 0; i < order; i++) dummy_list[i] = 0; // distribute dummies evenly EXCEPT TO LAST DEVICE distribute( table, initial_dist, dummy_list ); // save initial distribution of existing runs for (i = 0; i < order; i++) initial_dist[i] = table[dist][i] - dummy_list[i]; // setting up the devices // loading runs and dummies onto devices // the destination device: devices[order] = new Device( nruns ); // maximum size; empty for (i=0; i < order; i++) devices[i] = new Device ( initial_dist[i], dummy_list[i], runsize ); dest = devices[order]; // last one is destination for (i=0; i < order; i++) // the rest are sources sources[i] = devices[i]; delete [] initial_dist; delete [] dummy_list; } // end SetUp //-------------------------------------------------------// //---- do_round -------------------------------------// //-------------------------------------------------------// void do_round( Device* sources[], Device* dest, int order, long int rps, // records per seek long int& totseeks, long int& whos_empty, bool& done ) { // collect 1 run from each device to merge to destination int i; long int newrun = 0; long int thisrun = 0; long int seeks; long int setseeks; setseeks = 0; // seeks for this set for (i=0; i < order; i++) { // make sure it's available if (sources[i]->IsAvailable()) { thisrun = sources[i]->Gives(); // grab the run if (sources[i]->IsEmpty()) // is this device empty now? { done = true; whos_empty = i; } newrun += thisrun; // 'merge' it seeks = thisrun / rps; // count the seeks for this run setseeks += seeks; } }// end for // 'write' the new run to the destination dest->Gets(newrun); totseeks += setseeks; // add the seeks for the set just finished } // end do_round //-------------------------------------------------------// //---- polyphase -------------------------------------// //-------------------------------------------------------// void polyphase ( Device* sources[], Device*& dest, int order, int memsize ) { // does N-way merge each time (phase) where N is the order of the merge // For each phase: // collect 1 run from each source into 1 new run // when one source goes empty this phase is done // put the new run into dest // // After each phase: // switch dest and the source that went empty // check 1 other source: if it's empty too, we're done // we'll check source[0] unless that's the one that went empty // in which case we can check source[1] // long int setseeks; // seeks per set long int totseeks, grandtotal; // seeks per phase; merge long int recs_per_seek; // how many records we get for one seek long int whos_empty; // remembers which source went empty bool done, alldone; // flags for phase, merge Device* t; // for switching int i; recs_per_seek = memsize / order; grandtotal = 0; alldone = false; while (!alldone) { totseeks = 0; // for this phase done = false; whos_empty = 0; while (!(done)) { // collect 1 run from each device do_round( sources, dest, order, recs_per_seek, totseeks, whos_empty, done); } // while !done grandtotal += totseeks; // switch empty source and dest t = dest; dest = sources[whos_empty]; sources[whos_empty] = t; // check another source to see if >1 empty // if >1 empty; all MUST be empty so we're done if (whos_empty != 0) { if (sources[0]->IsEmpty()) alldone = true; } else { if (sources[1]->IsEmpty()) alldone = true; } } // end while !done cout << "Total seeks for Polyphase Merge: " << grandtotal << endl << endl; } // end polyphase