LifeGameMpiMaster::LifeGameMpiMaster(const field_t &field) : field(field), width(field.size()), height(field[0].size()), running(false), maxVersion(0) { MPI_Comm_size(MPI_COMM_WORLD, &nodesCount); int chunkSize = field.size() / (nodesCount - 1); if (chunkSize != 0) { bufSize = packSize(2 * chunkSize, height) + 1000; } else { bufSize = packSize(width, height) + 1000; } buf = (char*)malloc(bufSize); int curChunk = 0; for (size_t i = 1; i < nodesCount; ++i) { //(currentChunk, currentChunk + chunkSize) size_t messageLen; pack(field, curChunk - 1, 1 + (i == nodesCount - 1 ? width : curChunk + chunkSize), buf, messageLen); DBG(curChunk - 1 << " " << 1 + (i == nodesCount - 1 ? width : curChunk + chunkSize)); DBG("Sending field to " << i); DBG(toString(unpack(buf))); MPI_Send(buf, messageLen, MPI_CHAR, i, NEW_FIELD_TAG, MPI_COMM_WORLD); curChunk += chunkSize; } }
void randomCommand(const unsigned int &numRows, const unsigned int &numCols) { initializeStructures(); vector<bool> buf(numCols, false); field.resize(numRows, buf); field2.resize(numRows, buf); srand(time(0)); for (int i = 0; i < numRows; ++i) { for (int j = 0; j < numCols; ++j) { bool value = rand() % 2; field[i][j] = value; field2[i][j] = value; } } }
void check_field(const std::string& _path, const field_t& field, error_context_t& ctx) { std::string path = _path + "." + field.name; check_name(path, field.name, ctx); if(field.width == 0) ctx.add(error_t(error_t::WARNING, path, "field has width 0")); soc_word_t max = field.bitmask() >> field.pos; std::set< std::string > names; std::map< soc_word_t, std::string > map; for(size_t i = 0; i < field.enum_.size(); i++) { soc_word_t v = field.enum_[i].value; std::string n = field.enum_[i].name; std::string path_ = path + "." + n; check_name(path_, n, ctx); if(v > max) ctx.add(error_t(error_t::FATAL, path_, "value does not fit into the field")); if(names.find(n) != names.end()) ctx.add(error_t(error_t::FATAL, path, "duplicate name '" + n + "' in enums")); names.insert(n); if(map.find(v) != map.end()) ctx.add(error_t(error_t::WARNING, path, "'" + n + "' and '" + map[v] + "' have the same value")); map[v] = n; } }
WorkerThread::WorkerThread(int id, const field_t& allField, int from, int to, MasterThread& master) :id(id), topSem(0), bottomSem(0), topRead(1), bottomRead(1), master(master), stepCount(0) { //DBG("thread " << id << " got allField " << toString(allField)); //DBG("thread " << id << " got from " << from << " to " << to); //DBG("thread " << id << " allField size " << allField.size()); for (int i = from - 1; i < to + 1; ++i) { //DBG("i " << i); int normi = (i + allField.size()) % allField.size(); //DBG("normi " << normi); //DBG("allField[normi] " << toString(allField[normi])); field.push_back(allField[normi]); //DBG("field " << toString(field)); } //DBG("thread " << id << " initialized field " << toString(field)); }
MasterThread::MasterThread(const field_t& field, int threadCount) :WorkerThread(-1, field, 0, 0, *this), threadCount(threadCount), maxStepCount(0) { workerThreads = new WorkerThread*[threadCount]; int chunkSize = field.size() / threadCount; int currentChunk = 0; for (int i = 0; i < threadCount; ++i) { workerThreads[i] = new WorkerThread(i, field, currentChunk, (i == threadCount - 1) ? field.size() : currentChunk + chunkSize, *this); currentChunk += chunkSize; } for (int i = 0; i < threadCount; ++i) { workerThreads[i]->top = workerThreads[(i - 1 + threadCount) % threadCount]; workerThreads[i]->bottom = workerThreads[(i + 1 + threadCount) % threadCount]; } top = workerThreads[threadCount - 1]; bottom = workerThreads[0]; bottom->top = this; top->bottom = this; running = true; }
int startCommand(const string &filePath) { initializeStructures(); ifstream file; file.open(filePath); field.clear(); field2.clear(); while (!file.eof()) { vector<bool> buf; string str; getline(file, str); for (unsigned int i = 0; i < str.size(); ++i) { if (str[i] == '1') { buf.push_back(true); } if (str[i] == '0') { buf.push_back(false); } } field.push_back(buf); field2.push_back(buf); } file.close(); return field.size(); }
void statusCommand() { int x = field.size(); if (x < 1) { cout << "Error in taking number of rows\n"; return; } cout << "Iteration #" << stoppedIteration << "\n"; int y = field[0].size(); for (int i = 0; i < x; ++i) { for (int j = 0; j < y; ++j) { if (whichTable == 0) { cout << field[i][j] << " "; } else { cout << field2[i][j] << " "; } } cout << "\n"; } }
LifeGame::LifeGame(const field_t& field, int threadCount) : field(field), syncNeeded(false) { this->width = field.size(); this->height = field[0].size(); master = new MasterThread(field, threadCount); }
void* runParallel(void* arg) { args_t* arg_str = (args_t*)arg; int numIterations = arg_str->numIterations; int id = arg_str->pid; int x = field.size(); if (x < 1) { printf("Pid: %d - Error in taking number of rows\n", id); return NULL; } int y = field[0].size(); int range = ceil((double)x / (double)NUM_WS); int upBorder = min(range * id, x), downBorder = min(range * (id + 1), x); int down = (id + NUM_WS + 1) % NUM_WS, up = (id + NUM_WS - 1) % NUM_WS; field_t *ptr1, *ptr2; if (whichTable == 0) { ptr1 = &field; ptr2 = &field2; } else { ptr1 = &field2; ptr2 = &field; } for (int it = 0; it < numIterations; ++it) { for (int i = upBorder; i < downBorder; ++i) { for (int j = 0; j < y; ++j) { int numNeighbors = 0; int upper = (i + x - 1) % x; int lower = (i + x + 1) % x; int left = (j + y - 1) % y; int right = (j + y + 1) % y; if ((*ptr1)[upper][j]) { numNeighbors++; } if ((*ptr1)[upper][left]) { numNeighbors++; } if ((*ptr1)[upper][right]) { numNeighbors++; } if ((*ptr1)[lower][j]) { numNeighbors++; } if ((*ptr1)[lower][left]) { numNeighbors++; } if ((*ptr1)[lower][right]) { numNeighbors++; } if ((*ptr1)[i][left]) { numNeighbors++; } if ((*ptr1)[i][right]) { numNeighbors++; } if (!(*ptr1)[i][j] && numNeighbors == 3) { (*ptr2)[i][j] = true; } else if ((*ptr1)[i][j] && (numNeighbors < 2 || numNeighbors > 3)) { (*ptr2)[i][j] = false; } else { (*ptr2)[i][j] = (*ptr1)[i][j]; } } } swap(ptr1, ptr2); int lockStatus = sem_trywait(&iterationSem); if (lockStatus != 0) { if (gameFinished) { stoppedIteration += it; whichTable = (whichTable + it) % 2; printf("Stopped at iteration #%d\n", stoppedIteration); stopped = true; } pthread_mutex_lock(&mutexCV); sem_init(&iterationSem, 0, NUM_WS - 1); for (int i = 0; i < NUM_WS; ++i) { isReady[i] = true; } pthread_cond_broadcast(&iterationCV); pthread_mutex_unlock(&mutexCV); } pthread_mutex_lock(&mutexCV); while (!isReady[id]) { pthread_cond_wait(&iterationCV, &mutexCV); } isReady[id] = false; pthread_mutex_unlock(&mutexCV); if (stopped && gameFinished) { return NULL; } } if (id == 0) { stoppedIteration += numIterations; whichTable = (whichTable + numIterations) % 2; } return NULL; }