virtual void close(CRC32 &fileCRC) { CriticalBlock block(statsCs); mergeStats(fileStats, iFileIO); iFileIO.clear(); inputStream.clear(); fileCRC = inputCRC; }
void serializeStats(MemoryBuffer &mb) { CSlaveActivity::serializeStats(mb); CriticalBlock block(statsCs); CRuntimeStatisticCollection mergedStats(spillStats); mergeStats(mergedStats, sorter); mergedStats.serialize(mb); }
IRowStream * doLocalSelfJoin() { #if THOR_TRACE_LEVEL > 5 ActPrintLog("SELFJOIN: Performing local self-join"); #endif Owned<IThorRowLoader> iLoader = createThorRowLoader(*this, ::queryRowInterfaces(input), compare, isUnstable() ? stableSort_none : stableSort_earlyAlloc, rc_mixed, SPILL_PRIORITY_SELFJOIN); Owned<IRowStream> rs = iLoader->load(inputStream, abortSoon); mergeStats(spillStats, iLoader); // Not sure of the best policy if rs spills later on. PARENT::stop(); return rs.getClear(); }
virtual void serializeStats(MemoryBuffer &mb) { CSlaveActivity::serializeStats(mb); CriticalBlock b(joinHelperCrit); rowcount_t p = joinhelper?joinhelper->getLhsProgress():0; mb.append(p); CRuntimeStatisticCollection mergedStats(spillStats); mergeStats(mergedStats, sorter); // No danger of a race with reset() because that never replaces a valid sorter mergedStats.serialize(mb); }
void CDiskWriteSlaveActivityBase::serializeStats(MemoryBuffer &mb) { CriticalBlock block(statsCs); ProcessSlaveActivity::serializeStats(mb); mb.append(replicateDone); CRuntimeStatisticCollection activeStats(fileStats); mergeStats(activeStats, outputIO); activeStats.serialize(mb); }
void kill() { ActPrintLog("MSortSlaveActivity::kill"); { CriticalBlock block(statsCs); mergeStats(spillStats, sorter); sorter.clear(); } CSlaveActivity::kill(); }
virtual void close(CRC32 &fileCRC) { CriticalBlock block(statsCs); xmlParser.clear(); inputIOstream.clear(); if (checkFileCrc) { fileCRC.reset(~crcStream->queryCrc()); // MORE should prob. change stream to use CRC32 crcStream.clear(); } mergeStats(fileStats, iFileIO); iFileIO.clear(); }
void stop() { out.clear(); stopInput(input); dataLinkStop(); //Critical block { CriticalBlock block(statsCs); mergeStats(spillStats, iLoader); iLoader.clear(); } }
void CDiskWriteSlaveActivityBase::close() { try { if (out) { uncompressedBytesWritten = out->getPosition(); if (calcFileCrc) { if (diskHelperBase->getFlags() & TDWextend) { assertex(!"TBD need to merge CRC"); } else out->flush(&fileCRC); } else if (!abortSoon) out->flush(); out.clear(); } else if (outraw) { outraw->flush(); uncompressedBytesWritten = outraw->tell(); outraw.clear(); } { CriticalBlock block(statsCs); mergeStats(fileStats, outputIO); outputIO.clear(); } if (!rfsQueryParallel && dlfn.isExternal() && !lastNode()) { rowcount_t rows = processed & THORDATALINK_COUNT_MASK; ActPrintLog("External write done, signalling next (row count = %" RCPF "d)", rows); CMessageBuffer msg; msg.append(rows); msg.append(tempExternalName); queryJobChannel().queryJobComm().send(msg, queryJobChannel().queryMyRank()+1, mpTag); } } catch (IException *e) { ActPrintLogEx(&queryContainer(), e, thorlog_null, MCwarning, "Error closing file: %s", fName.get()); abortSoon = true; removeFiles(); throw e; } if (abortSoon) removeFiles(); }
virtual void close(CRC32 &fileCRC) { xmlParser.clear(); inputIOstream.clear(); if (checkFileCrc) { fileCRC.reset(~crcStream->queryCrc()); // MORE should prob. change stream to use CRC32 crcStream.clear(); } Owned<IFileIO> partFileIO; { CriticalBlock block(statsCs); partFileIO.setown(iFileIO.getClear()); } mergeStats(fileStats, partFileIO); }
virtual void gatherStats(CRuntimeStatisticCollection & merged) { CriticalBlock block(statsCs); CDiskPartHandlerBase::gatherStats(merged); mergeStats(merged, iFileIO); }
int main(int argc, char **argv) { #ifdef USE_MPI MPI_Init(&argc, &argv); #endif if (argc != 5) { LOG_ERROR("I want width, height, zombies, iterations.\n"); #ifdef USE_MPI MPI_Finalize(); #endif exit(1); } int width = atoi(argv[1]); int height = atoi(argv[2]); int people = (int) (width * height * INITIAL_DENSITY); int zombies = atoi(argv[3]); int iters = atoi(argv[4]); initRandom(0); WorldPtr input, output; double ratio = divideWorld(&width, &height, &input, &output); // there should not be any output prior to this point #ifdef REDIRECT initRedirectToFiles(input); #endif LOG_DEBUG("World size is %d x %d at position [%d, %d] of %d x %d\n", input->localWidth, input->localHeight, input->globalX, input->globalY, input->globalColumns, input->globalRows); if (input->globalX == 0 && input->globalY == 0) { randomDistribution(input, people * ratio, zombies, 0); } else { // no zombies elsewhere randomDistribution(input, people * ratio, 0, 0); } #ifndef NIMAGES printWorld(input, false); #endif Timer timer = startTimer(); Stats cumulative = NO_STATS; for (int i = 0; i < iters; i++) { simulateStep(input, output); output->stats.clock = cumulative.clock = output->clock; Stats stats = output->stats; mergeStats(&cumulative, stats, false); printStatistics(output, cumulative); WorldPtr temp = input; input = output; output = temp; input->stats = stats; } double elapsedTime = getElapsedTime(timer); #ifdef _OPENMP int numThreads = omp_get_max_threads(); #else int numThreads = 1; #endif LOG_TIME("Simulation took %f milliseconds with %d threads\n", elapsedTime, numThreads); // this is a clean up // we destroy both worlds destroyWorld(input); destroyWorld(output); destroyRandom(); #ifdef REDIRECT finishRedirectToFiles(); #endif #ifdef USE_MPI MPI_Finalize(); #endif }
/** * Order of actions: * a) death of human or infected * b) decomposition of zombie * c) transition of infected to zombie */ static void simulateStep1(WorldPtr input, WorldPtr output) { simClock clock = output->clock; // we want to force static scheduling because we suppose that the load // is distributed evenly over the map and we need to have predictable locking #ifdef _OPENMP // at least three columns per thread int threads = omp_get_max_threads(); int numThreads = MIN(MAX(input->localWidth / 3, 1), threads); #pragma omp parallel for num_threads(numThreads) schedule(static) #endif for (int x = input->xStart; x < input->xEnd; x++) { Stats stats = NO_STATS; for (int y = input->yStart; y <= input->yEnd; y++) { EntityPtr entity = GET_CELL_PTR(input, x, y); if (entity->type == NONE) { continue; } // Death of living entity if (entity->type == HUMAN || entity->type == INFECTED) { if (randomDouble() < getDeathRate(entity, clock)) { if (entity->type == HUMAN) { if (entity->gender == FEMALE) { stats.humanFemalesDied++; } else { stats.humanMalesDied++; } } else { if (entity->gender == FEMALE) { stats.infectedFemalesDied++; } else { stats.infectedMalesDied++; } } LOG_EVENT("A %s died\n", entity->type == HUMAN ? "Human" : "Infected"); // just forget this entity entity->type = NONE; } } // Decompose Zombie if (entity->type == ZOMBIE) { if (randomDouble() < getDecompositionRate(entity, clock)) { stats.zombiesDecomposed++; LOG_EVENT("A Zombie decomposed\n"); // just forgot this entity entity->type = NONE; } } // Convert Infected to Zombie if (entity->type == INFECTED) { if (randomDouble() < PROBABILITY_BECOME_ZOMBIE) { if (entity->gender == FEMALE) { stats.infectedFemalesBecameZombies++; } else { stats.infectedMalesBecameZombies++; } toZombie(entity, clock); LOG_EVENT("An Infected became Zombie\n"); } } } #ifdef _OPENMP #pragma omp critical (StatsCriticalRegion2) #endif { mergeStats(&output->stats, stats, true); } } }
/** * Order of actions: * a) transition of human into infected * b) giving birth to children - changes input * c) making love - changes input * d) movement */ static void simulateStep2(WorldPtr input, WorldPtr output) { simClock clock = output->clock; // notice that we iterate over xx and yy // and the real x and y are randomly switched between two directions double xxDir = randomDouble(); double yyDir = randomDouble(); // we want to force static scheduling because we suppose that the load // is distributed evenly over the map and we need to have predictable locking #ifdef _OPENMP // at least three columns per thread int threads = omp_get_max_threads(); int numThreads = MIN(MAX(input->localWidth / 3, 1), threads); #pragma omp parallel for num_threads(numThreads) schedule(static) #endif for (int xx = input->xStart; xx <= input->xEnd; xx++) { int x = (xxDir < 0.5) ? xx : (input->xEnd + input->xStart - xx); // stats are counted per column and summed at the end Stats stats = NO_STATS; lockColumn(output, x); for (int yy = input->yStart; yy <= input->yEnd; yy++) { int y = (yyDir < 0.5) ? yy : (input->yEnd + input->yStart - yy); Entity entity = GET_CELL(input, x, y); if (entity.type == NONE) { continue; } // Convert Human to Infected if (entity.type == HUMAN) { int zombieCount = countNeighbouringZombies(input, x, y); double infectionChance = zombieCount * PROBABILITY_INFECTION; if (randomDouble() <= infectionChance) { if (entity.gender == FEMALE) { stats.humanFemalesBecameInfected++; } else { stats.humanMalesBecameInfected++; } toInfected(&entity, clock); LOG_EVENT("A Human became infected\n"); } } // Here are performed natural processed of humans and infected if (entity.type == HUMAN || entity.type == INFECTED) { // giving birth if (entity.gender == FEMALE && entity.children > 0) { if (entity.origin + entity.borns <= clock) { if (entity.type == HUMAN) { stats.humanFemalesGivingBirth++; } else { stats.infectedFemalesGivingBirth++; } Entity * freePtr; while (entity.children > 0 && (freePtr = getFreeAdjacent(input, output, x, y)) != NULL) { Entity child = giveBirth(&entity, clock); if (child.type == HUMAN) { if (child.gender == FEMALE) { stats.humanFemalesBorn++; } else { stats.humanMalesBorn++; } } else { if (child.gender == FEMALE) { stats.infectedFemalesBorn++; } else { stats.infectedMalesBorn++; } } *freePtr = child; LOG_EVENT("A %s child was born\n", child.type == HUMAN ? "Human" : "Infected"); } } else { if (entity.type == HUMAN) { stats.humanFemalesPregnant++; } else { stats.infectedFemalesPregnant++; } } } // making love if (entity.gender == FEMALE && entity.children == 0 && clock >= entity.origin + entity.fertilityStart && clock < entity.origin + entity.fertilityEnd) { // can have baby EntityPtr adjacentMale = findAdjacentFertileMale(input, x, y, clock); if (adjacentMale != NULL) { stats.couplesMakingLove++; makeLove(&entity, adjacentMale, clock, input->stats); stats.childrenConceived += entity.children; LOG_EVENT("A couple made love\n"); } } } if (entity.type == HUMAN) { if (entity.gender == FEMALE) { stats.humanFemales++; } else { stats.humanMales++; } } else if (entity.type == INFECTED) { if (entity.gender == FEMALE) { stats.infectedFemales++; } else { stats.infectedMales++; } } else { stats.zombies++; } // MOVEMENT bearing bearing_ = getBearing(input, x, y); // optimal bearing bearing_ += getRandomBearing() * BEARING_FLUCTUATION; Direction dir = bearingToDirection(bearing_); if (dir != STAY) { double bearingRandomQuotient = (randomDouble() - 0.5) * BEARING_ABS_QUOTIENT_VARIANCE + BEARING_ABS_QUOTIENT_MEAN; entity.bearing = bearing_ / cabsf(bearing_) * bearingRandomQuotient; } else { entity.bearing = bearing_; } // some randomness in direction // the entity will never go in the opposite direction if (dir != STAY) { if (randomDouble() < getMaxSpeed(&entity, clock)) { double dirRnd = randomDouble(); if (dirRnd < DIRECTION_MISSED) { dir = DIRECTION_CCW(dir); // turn counter-clock-wise } else if (dirRnd < DIRECTION_MISSED * 2) { dir = DIRECTION_CW(dir); // turn clock-wise } else if (dirRnd > DIRECTION_FOLLOW + DIRECTION_MISSED * 2) { dir = STAY; } } else { dir = STAY; } } else { // if the entity would STAY, we'll try again to make it move // to make the entity bearing variable in terms of absolute value double bearingRandomQuotient = (randomDouble() - 0.5) * BEARING_ABS_QUOTIENT_VARIANCE + BEARING_ABS_QUOTIENT_MEAN; bearing_ += getRandomBearing() * bearingRandomQuotient; dir = bearingToDirection(bearing_); } // we will try to find the cell in the chosen direction CellPtr destPtr = NULL; if (dir != STAY) { destPtr = IF_CAN_MOVE_TO(x, y, dir); if (randomDouble() < MOVEMENT_TRY_ALTERNATIVE) { if (destPtr == NULL) { destPtr = IF_CAN_MOVE_TO(x, y, DIRECTION_CCW(dir)); } if (destPtr == NULL) { destPtr = IF_CAN_MOVE_TO(x, y, DIRECTION_CW(dir)); } } } if (destPtr == NULL) { destPtr = GET_CELL_PTR(output, x, y); } // actual assignment of entity to its destination *destPtr = entity; } unlockColumn(output, x); #ifdef _OPENMP #pragma omp critical (StatsCriticalRegion2) #endif { mergeStats(&output->stats, stats, true); } } }