Frage

Wir haben eine C ++ Klasse, die im Grunde liest und schreibt Vektoren aus einer Binärdatei. Eine beispielhafte Lesefunktion, die einen einzelnen Vektor in den Speicher geladen sieht wie folgt aus:

int load (const __int64 index, T* values) const {

 int re = _fseeki64(_file, index * _vectorSize + _offsetData, SEEK_SET); 
 assert(re == 0);

 size_t read = fread(values, sizeof(T), _vectorElements, _file);
 assert(read == _vectorElements);

 return 0;}

Out-Programme werden mit OpenMP multithreaded und mehr Threads Zugriff auf die gleiche Datei zur gleichen Zeit. Um Probleme zu vermeiden, da mehrere Threads decken wir immer den Funktionsaufruf innerhalb einer OpenMP kritischen Aussage:

#pragma omp critical {
    load(...);
}

Ich weiß, dass das Microsoft Visual C ++ Runtime ... mehrere Funktionen wie _fseek_nolock, _fread_nolock, _fwrite_nolock und so weiter enthält zum Beispiel der _fread_nolock() Funktion als

beschrieben wird
  

Diese Funktion ist eine Non-Locking-Version von fread. Es ist identisch mit fread, außer dass es nicht vor Störungen durch andere Threads geschützt ist. Es könnte schneller sein, weil es nicht den Aufwand für die Aussperrung andere Threads nicht entstehen. Verwenden Sie diese Funktion nur in Thread-sicheren Kontexten wie Single-Threaded-Anwendungen oder in denen der anruf Umfang bereits Thread Isolation behandelt.

Nun meine Frage: Ich verstehe, dass die Funktionsblöcke „einspringenden“ Anrufe, so wird kein anderer Thread die Funktion eingeben, bevor andere Threads zurückgekehrt. Allerdings verstehe ich nicht, warum es notwendig ist, eine einzelne Funktion auf diese Weise zu schützen. IMHO Alle Funktionen, die / ändern Zugriff auf den Dateizeiger (_file in dem Codebeispiel) müssen geschützt werden und deshalb threadsicher gemacht werden. Dies erfordert eine Sperre um den gesamten Funktionsblock zu bauen, den actuall ruft die Standard-C-Funktionen fseek und fread, so dass ich nicht den Punkt der Bereitstellung solche nicht-blockierende Funktionen sehen.

Kann jemand mir erklären, diese Verriegelungsmechanismen, weil ich unsere paranoid Sperrschema nehme eine gewisse Leistung vergeudet?

Vielen Dank im Voraus!

War es hilfreich?

Lösung

Für einige einfachen Codes, die Sperre in der FILE * ausreichend. Betrachten wir eine grundlegende Logging-Infrastruktur, wo Sie alle Themen wollen über eine gemeinsame FILE * loggt sein. Die interne Sperre wird sicherstellen, dass die Datei * wird nicht von mehreren Threads beschädigt werden und da jede Protokollzeile allein stehen soll, spielt es keine Rolle, wie die einzelnen Anrufe verschachteln.

Andere Tipps

Wenn Sie die Microsoft multithreaded C-Laufzeit alle Funktionen nutzen, die globale oder statische Variablen müssen nur richtig funktionieren (wie printf und fread, fragen Sie mich nicht, warum sie Globals obwohl benötigen). Jedoch Sie kann immer noch nicht eine FILE * Struktur an eine Funktion, die es schreibt und erwartet, dass es Thread-sicher sein.

So die Microsofts „thread-safe“ Funktionen Gewinde sind sicher nur in dem Sinne, dass sie einspringenden, dh alle Zugriffe auf Globals und Statik ist mit einem Mutex oder ähnliches getan. Aber nicht in dem Sinne, dass man zwei fprintf () zur gleichen Zeit mit der gleichen Datei aufrufen kann *.

Quelle: http://msdn.microsoft .com / en-us / library / 1bh5ewb2% 28VS.71% 29.aspx

Wenn Ihre Anwendung bereits serialisierten Zugriff guranteeing Griffe Datei, können Sie eine bessere Leistung, wenn man die c-runtime sagen, es ist eigene Serialisierung zu umgehen. Dies ist der Zweck der _fread_nolock, etc Funktionen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top