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 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" ); }