Ist mit std::async oft für kleine Aufgaben performance-freundlich?

Geben ein paar Informationen zum hintergrund, ich bin Verarbeitung einer Datei gespeichert haben, und nach der Verwendung des regulären Ausdrucks, so teilen Sie die Datei in die Komponente Gegenstände, die ich dann verarbeiten muss, das Objekt die Daten basierend auf welche Art von Objekt es sich handelt.

Mein Aktueller Gedanke ist die Verwendung von Parallelität, um ein wenig etwas von einem performance-Gewinn, da das laden jedes Objekt ist unabhängig von einander. So, ich werde zu definieren, eine LoadObject - Funktion, die Annahme einer std::string für jede Art von Objekt, ich werde zu Handhabung und rufen dann std::async wie folgt:

void LoadFromFile( const std::string& szFileName )
{
     static const std::regex regexObject( "=== ([^=]+) ===\\n((?:.|\\n)*)\\n=== END \\1 ===", std::regex_constants::ECMAScript | std::regex_constants::optimize );

     std::ifstream inFile( szFileName );
     inFile.exceptions( std::ifstream::failbit | std::ifstream::badbit );

     std::string szFileData( (std::istreambuf_iterator<char>(inFile)), (std::istreambuf_iterator<char>()) );

     inFile.close();

     std::vector<std::future<void>> vecFutures;

     for( std::sregex_iterator itObject( szFileData.cbegin(), szFileData.cend(), regexObject ), end; itObject != end; ++itObject )
     {
          //Determine what type of object we're loading:
          if( (*itObject)[1] == "Type1" )
          {
               vecFutures.emplace_back( std::async( LoadType1, (*itObject)[2].str() ) );
          }
          else if( (*itObject)[1] == "Type2" )
          {
               vecFutures.emplace_back( std::async( LoadType2, (*itObject)[2].str() ) );
          }
          else
          {
               throw std::runtime_error( "Unexpected type encountered whilst reading data file." );
          }
     }

     //Make sure all our tasks completed:
     for( auto& future : vecFutures )
     {
           future.get();
     }
}

Beachten Sie, dass es mehr als 2 Arten in der Anwendung (dies war nur ein kurzes Beispiel) und möglicherweise Tausende von Objekten in die Datei gelesen werden.

Ich bin mir bewusst, dass die Schaffung von zu vielen threads ist oft schlecht für die Leistung, wenn es überschreitet die maximale hardware-Parallelität durch Kontext-switches, aber wenn ich mich erinnere richtig die C++ - Laufzeit-soll überwachen Sie die Anzahl der threads, die erstellt und Zeitplan std::async angemessen (ich glaube im Fall von Microsoft Ihre ConcRT-Bibliothek ist verantwortlich für diese?), also, der obige code kann immer noch zu einer Leistungsverbesserung führen?

Vielen Dank im Voraus!

  • Der obige code kann in der Tat Ergebnis in performance-Verbesserung, aber ich würde sagen, es hängt von der Menge der Arbeit, die jede LoadTypeX tut. Ist es genug zu überwiegen, der overhead durch Sie entstehen in deinem Haupt-thread für starten und warten und synchronisieren? Nicht zu vergessen die erhöhte Anzahl von cache-misses und false teilhaben. Und andere Sanktionen im Zusammenhang mit Multithreading-Programmierung. Also, wenn Sie Ihre Objekte groß sind und Ihre asynchrone laden Funktionen sind dabei erhebliche Arbeit, ich würde sagen, es ist wohl Wert es. Aber warum gehst du nicht einfach Messen?
  • Unrelated: erstellen Sie einen Vektor von 100 Standard-futures konstruiert, und dann anfügen Ihre real-futures am Ende. Aufruf get() auf diese default-konstruiert futures Ergebnisse zu undefiniertem Verhalten.
  • Haben Sie profiliert Ihren code? Ich hätte erwartet, dass die I/O-Kosten für Zwerg die Verarbeitung Kosten bis zu dem Punkt, wo der Gewinn aus der Aufteilung der Verarbeitung in die Gewinde vielleicht nicht messbar.
  • Streng genommen, gibt es keine Möglichkeit zu wissen. Sie wissen nicht, wie oder Wann std::async läuft eine Aufgabe. Alles, was Sie wissen, ist, dass, wenn future::get Renditen, das Ergebnis fertig sein wird. Die Aufgabe ausführen, asynchron in einem anderen thread oder in eine Faser, oder es könnte sogar synchron laufen, wenn Sie anrufen get. Letzteres ist eine Art von "Betrug", aber es ist zulässig.
Schreibe einen Kommentar