2015-08-11 20 views
13

Sto utilizzando std::futures per elaborare in parallelo il mio algoritmo. Ho diviso le informazioni in pool reciprocamente esclusivi e poi ho eseguito la stessa operazione su ciascun pool in una propria discussione. Il codice è simile al seguente:Elaborazione parallela dei futures C++

class Processor 
{ 
public: 
    Processor(const std::string &strVal) : m_strVal(strVal) 
    { 
    } 

    std::string GetVal() const {return m_strVal;} 

    std::vector<std::string> Do() 
    { 
     // do some processing - this can throw an exception 
    } 

private: 
    std::string m_strVal; 
}; 

class ParallelAlgo 
{ 
private: 
    std::vector<std::string> m_vecMasterResults; 

public: 

    ProcessingFunction(const std::vector<std::string> &vecInfo) 
    { 
     // vecInfo holds mutually exclusive pools 

     std::vector<std::future<std::vector<std::string> > > vecFutures(vecInfo.size()); 

     try 
     { 
      for (auto n = 0 ; n < vecInfo.size() ; n++) 
      { 
       vecFuture[n] = std::async(std::launch::async, &ParallelAlgo::WorkFunc, vecInfo[n].GetVal()); 
      } 

      for (auto it = vecFutures.begin() ; it != vecFutures.end() ; ++it) 
      { 
       std::vector<std::string> RetVal = it->get(); 
       m_MasterResults.insert(m_MasterResults.begin(), RetVal.begin(), RetVal.end()); 
       vecFutures.erase(it); 
      } 
     } 
     catch (exception &e) 
     { 
      for (auto it = vecFutures.begin() ; it != vecFuture.end() ; ++it) 
      { 
       // race condition? 
       if (it->valid()) 
       { 
        it->wait_for(std::chrono::second(0)); 
       } 
      } 
     } 
    } 

    std::vector<std::string> ParallelAlgo::WorkFunc(const std::string &strVal) 
    { 
     Processor _Proccessor(strVal); 
     return _Processor.Do(); 
    } 
}; 

La mia domanda è come gestire la situazione quando viene generata un'eccezione in Processor:Do()? Attualmente rilevo l'eccezione utilizzando future, quindi attendo zero secondi per ogni future che non è stato completato; questo va bene - questi thread terminano semplicemente e l'elaborazione non sarà completata. Tuttavia, non ho introdotto una condizione di gara nel blocco catch. un future potrebbe finire tra le chiamate a valid() e wait_for(), o non è un problema dato che non sto chiamando get() su questi futuri incompleti?

+1

Chiamare 'wait_for' su un thread' finito' funziona esattamente come ci si aspetterebbe, ritorna immediatamente. Non vedo il problema – nwp

+0

Come non fai nulla con l'eccezione, non potresti non preoccuparti solo dei thread incompleti? I distruttori di 'std :: future' verranno bloccati fino al termine dell'elaborazione asincrona, se necessario, ma per quanto ho capito è quello che vuoi. –

+1

C'è un bug nel codice di esempio. Chiamare 'vecFutures.erase (it);' invaliderà 'it' e usarlo ulteriormente nel ciclo for è UB. – DaBrain

risposta

3

Una chiamata a valid controlla solo se è presente uno stato condiviso corrispondente, che rimane valido per un thread finito finché non si chiama get su di esso.

Non c'è condizione di gara lì.