void PreDistributeWorkSync( CDSInfo *pInfo ) { if ( g_bMPIMaster ) { // Send a message telling all the workers we're ready to go on this DistributeWork call. MessageBuffer mb; PrepareDistributeWorkHeader( &mb, DW_SUBPACKETID_MASTER_READY ); VMPI_SendData( mb.data, mb.getLen(), VMPI_PERSISTENT ); } else { if ( g_iVMPIVerboseLevel >= 1 ) Msg( "PreDistributeWorkSync: waiting for master\n" ); // Wait for the master's message saying it's ready to go. while ( g_iMasterReadyForDistributeWorkCall < g_iCurDSInfo ) { VMPI_DispatchNextMessage(); } if ( g_iVMPIVerboseLevel >= 1 ) Msg( "PreDistributeWorkSync: master ready\n" ); // Now tell the master we're ready. MessageBuffer mb; PrepareDistributeWorkHeader( &mb, DW_SUBPACKETID_WORKER_READY ); VMPI_SendData( mb.data, mb.getLen(), VMPI_MASTER_ID ); } }
void TellMasterThatWorkerStartedAWorkUnit( MessageBuffer &mb, CDSInfo *pInfo, WUIndexType iWU ) { mb.setLen( 0 ); PrepareDistributeWorkHeader( &mb, DW_SUBPACKETID_WU_STARTED ); mb.write( &iWU, sizeof( iWU ) ); VMPI_SendData( mb.data, mb.getLen(), VMPI_MASTER_ID, k_eVMPISendFlags_GroupPackets ); }
void SendQDirInfo() { char cPacketID[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DIRECTORIES }; MessageBuffer mb; mb.write( cPacketID, 2 ); mb.write( gamedir, strlen( gamedir ) + 1 ); mb.write( qdir, strlen( qdir ) + 1 ); VMPI_SendData( mb.data, mb.getLen(), VMPI_PERSISTENT ); }
void DistributeWork_Master( CDSInfo *pInfo, ProcessWorkUnitFn processFn, ReceiveWorkUnitFn receiveFn ) { pInfo->m_WorkerInfo.m_pProcessFn = processFn; pInfo->m_MasterInfo.m_ReceiveFn = receiveFn; VMPITracker_Start( (int) pInfo->m_nWorkUnits ); g_bMasterDistributingWork = true; g_pCurDistributorMaster->DistributeWork_Master( pInfo ); g_bMasterDistributingWork = false; VMPITracker_End(); // Tell all workers to move on. MessageBuffer mb; PrepareDistributeWorkHeader( &mb, DW_SUBPACKETID_MASTER_FINISHED ); VMPI_SendData( mb.data, mb.getLen(), VMPI_PERSISTENT ); // Clear the master's local completed work unit list. CMasterWorkUnitCompletedList *pList = g_MasterWorkUnitCompletedList.Lock(); pList->m_CompletedWUs.RemoveAll(); g_MasterWorkUnitCompletedList.Unlock(); }
void VMPI_WorkerThread( int iThread, void *pUserData ) { CDSInfo *pInfo = (CDSInfo*)pUserData; CWorkerInfo *pWorkerInfo = &pInfo->m_WorkerInfo; // Get our index for running work units uint64 idxRunningWorkUnit = (uint64) iThread; { CCriticalSectionLock csLock( &pWorkerInfo->m_WorkUnitsRunningCS ); csLock.Lock(); pWorkerInfo->m_WorkUnitsRunning.ExpandWindow( idxRunningWorkUnit, ~0ull ); csLock.Unlock(); } MessageBuffer mb; PrepareDistributeWorkHeader( &mb, DW_SUBPACKETID_WU_RESULTS ); MessageBuffer mbStartedWorkUnit; // Special messagebuffer used to tell the master when we started a work unit. while ( g_iMasterFinishedDistributeWorkCall < g_iCurDSInfo && !g_bVMPIEarlyExit ) { WUIndexType iWU; // Quit out when there are no more work units. if ( !g_pCurDistributorWorker->GetNextWorkUnit( &iWU ) ) { // Wait until there are some WUs to do. This should probably use event handles. VMPI_Sleep( 10 ); continue; } CCriticalSectionLock csLock( &pWorkerInfo->m_WorkUnitsRunningCS ); csLock.Lock(); // Check if this WU is not running WUIndexType const *pBegin = &pWorkerInfo->m_WorkUnitsRunning.Get( 0ull ), *pEnd = pBegin + pWorkerInfo->m_WorkUnitsRunning.PastVisibleIndex(); WUIndexType const *pRunningWu = GenericFind( pBegin, pEnd, iWU ); if ( pRunningWu != pEnd ) continue; // We are running it pWorkerInfo->m_WorkUnitsRunning.Get( idxRunningWorkUnit ) = iWU; csLock.Unlock(); // Process this WU and send the results to the master. mb.setLen( 4 ); mb.write( &iWU, sizeof( iWU ) ); // Set the current WU for the stats database. if ( iThread >= 0 && iThread < 4 ) { g_ThreadWUs[iThread] = iWU; } // Tell the master we're starting on this WU. TellMasterThatWorkerStartedAWorkUnit( mbStartedWorkUnit, pInfo, iWU ); pWorkerInfo->m_pProcessFn( iThread, iWU, &mb ); g_pCurDistributorWorker->NoteLocalWorkUnitCompleted( iWU ); VMPI_SendData( mb.data, mb.getLen(), VMPI_MASTER_ID, /*k_eVMPISendFlags_GroupPackets*/0 ); // Flush grouped packets every once in a while. //VMPI_FlushGroupedPackets( 1000 ); } if ( g_iVMPIVerboseLevel >= 1 ) Msg( "Worker thread exiting.\n" ); }