/** * Called by the master and will start awaiting processes (signal to them to start) if required. * By default this works as a process pool, so if there are not enough processes to workers then it will quit * but this can be changed by modifying options in the pool. * It takes in the awaiting worker number to send rank data to/from, the parent rank of the process to start * and returns the process rank that this awaiting worker was on. In the default case of #workers > pool capacity * causing an abort, then this will only be called to start single workers and as such the parent ID and return rank * will match perfectly. If you change the options to allow for workers to queue up if there is not enough MPI * capacity then the parent and return rank will be -1 for all workers started which do not match the provided awaiting Id */ static int startAwaitingProcessesIfNeeded(int awaitingId, int parent) { int awaitingProcessMPIRank=-1; if(PP_processesAwaitingStart) { int i; for(i=0; i<PP_numProcs-1; i++) { if(!PP_active[i]) { PP_active[i]=1; PP_numActive++; struct PP_Control_Package out_command = createCommandPackage(PP_WAKE); out_command.data = awaitingId == PP_processesAwaitingStart ? parent : -1; if (PP_DEBUG) printf("[Master] Starting process %d\n", i+1); MPI_Send(&out_command, 1, PP_COMMAND_TYPE, i+1, PP_CONTROL_TAG, MPI_COMM_WORLD); if (awaitingId == PP_processesAwaitingStart) awaitingProcessMPIRank = i+1; // Will return this rank to the caller PP_processesAwaitingStart--; if (PP_processesAwaitingStart == 0) break; } if(i==PP_numProcs-2) { //If I reach this point, I must have looped through the whole array and found no available processes if(PP_QuitOnNoProcs) { errorMessage("No more processes available"); } if(PP_IgnoreOnNoProcs) { fprintf(stderr,"[ProcessPool] Warning. No processes available. Ignoring launch request.\n"); PP_processesAwaitingStart--; } // otherwise, do nothing; a process may become available on the next iteration of the loop } } } return awaitingProcessMPIRank; }
/** * A worker can instruct the master to shutdown the process pool. The master can also call this * but it does nothing (they just need to call the finalisation step) */ void shutdownPool() { if (PP_myRank != 0) { if (PP_DEBUG) printf("[Worker] Commanding a pool shutdown\n"); struct PP_Control_Package out_command = createCommandPackage(PP_RUNCOMPLETE); MPI_Ssend(&out_command, 1, PP_COMMAND_TYPE, 0, PP_CONTROL_TAG, MPI_COMM_WORLD); } }
// Отправка серверу уведомленя о том, что клиент готов к получению данных int Client::slotSendClientIsReady() { if (mClientSocket == 0) return -1; mClientSocket->write(createCommandPackage(CommandType::IsReady)); return 0; }
/** * Each process calls this to finalise the process pool */ void processPoolFinalise() { if (PP_myRank == 0) { if (PP_active != NULL) free(PP_active); int i; for(i=0; i<PP_numProcs-1; i++) { if (PP_DEBUG) printf("[Master] Shutting down process %d\n", i); struct PP_Control_Package out_command = createCommandPackage(PP_STOP); MPI_Send(&out_command, 1, PP_COMMAND_TYPE, i+1, PP_CONTROL_TAG, MPI_COMM_WORLD); //printf("MASTER SENT STOP TO %d\n", i+1); } } MPI_Barrier(MPI_COMM_WORLD); MPI_Type_free(&PP_COMMAND_TYPE); }
/** * A worker or the master can instruct to start another worker process */ int startWorkerProcess() { if (PP_myRank == 0) { PP_processesAwaitingStart++; return startAwaitingProcessesIfNeeded(PP_processesAwaitingStart, 0); } else { int workerRank; struct PP_Control_Package out_command = createCommandPackage(PP_STARTPROCESS); MPI_Send(&out_command, 1, PP_COMMAND_TYPE, 0, PP_CONTROL_TAG, MPI_COMM_WORLD); // Receive the rank that this worker has been placed on - if you change the default option from aborting when // there are not enough MPI processes then this may be -1 MPI_Recv(&workerRank, 1, MPI_INT, 0, PP_PID_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); return workerRank; } }
/** * Called by the worker at the end of each task when it has finished and is to sleep. Will be interrupted from * sleeping when given a command from the master, which might be to do more work of shutdown * Returns one (true) if the caller should do some more work or zero (false) if it is to quit */ int workerSleep() { if (PP_myRank != 0) { if (in_command.command==PP_WAKE) { // The command was to wake up, it has done the work and now it needs to switch to sleeping mode struct PP_Control_Package out_command = createCommandPackage(PP_SLEEPING); MPI_Send(&out_command, 1, PP_COMMAND_TYPE, 0, PP_CONTROL_TAG, MPI_COMM_WORLD); if (PP_pollRecvCommandRequest != MPI_REQUEST_NULL) MPI_Wait(&PP_pollRecvCommandRequest, MPI_STATUS_IGNORE); } return handleRecievedCommand(); } else { errorMessage("Master process called worker poll"); return 0; } }
// Слот - "Превышено время ожидания ответа от сервера" int Client::slotCheckActivity() { mClientSocket->write(createCommandPackage(CommandType::IsAlive)); return 0; }