Ist es auf einer wirklichen Hardware möglich, dass der aktualisierte Wert einer Atomgülleger über einen indirekten Pfad C++

Programme in C++. Entwicklerforum
Anonymous
 Ist es auf einer wirklichen Hardware möglich, dass der aktualisierte Wert einer Atomgülleger über einen indirekten Pfad

Post by Anonymous »

Ist es in jeder wirklichen Hardware in der realen Welt möglich, für den aktualisierten Wert einer atomaren Ganzzahl, die von einem Thread geschrieben wurde, um früher über einen indirekten Pfad zu einem anderen Thread sichtbar zu werden, wobei ein Dritter (Thread) den Wert durch einen anderen atomischen Ganze weiterleitet, als auf einem direkten Pfad (der ursprünglich geschriebene Atom -Integer). DOCs: (https://git.kernel.org/pub/scm/linux/ke ... y-barriers Was ich in C ++ - Code geworden und Kommentare hinzugefügt habe, um meine Frage zu klären. Meine Frage in den Kontext des Beispiels umformulieren: < /p>
  • Ist es möglich, dass der neue Wert von y für Thread3 sichtbar ist, bevor der neue Wert von x sichtbar für Thread3 ist?

    Code: Select all

    #define general_barrier std::atomic_thread_fence(memory_order_seq_cst)
    #define read_barrier    std::atomic_thread_fence(memory_order_acquire)
    
    // Though not written explicitly, these initially have value 0.
    std::atomic x, y;
    
    void thread1() {
    x.store(1, std::memory_order_relaxed); // W0, value goes to thread2 and thread3
    // No barrier should be needed here because there's only one operation,
    // so there is nothing to reorder.
    }
    
    void thread2() {
    int r2 = x.load(std::memory_order_relaxed); // R0
    general_barrier; // F1, is this full memory barrier really necessary?
    // You can't do the write until you know the final (non speculative) value of r2,
    // so the read MUST have completed before the write.
    // Therefore I actually think no barrier should be needed at all here.
    y.store(r2, std::memory_order_relaxed); // W1, direct forwarding of value of x
    }
    
    void thread3() {
    int r3_a = y.load(std::memory_order_relaxed); // R1, value of x via indirect path
    read_barrier; // F2, required to prevent reordering of loads
    int r3_b = x.load(std::memory_order_relaxed); // R2, value of x via direct path
    
    if( r3_a == 1 ){
    assert(r3_b == 1); // Is it possible for this to go wrong?
    }
    }
    
    Über das Beispiel mit General_Barrier sagen sie Folgendes (sie nennen es CPU anstelle von Thread, obwohl ich es allgemein halte, vorausgesetzt, dass die Threads möglicherweise auf separaten Kernen oder CPUs laufen oder nicht. Speichern Sie die Ladung von Y,
    und CPU 3 von y zurück. 1. Dies zeigt, dass CPU 1 -Store
    bis x CPU 2 von X und CPU 2 von Y vorausgeht. Aus X. Die Frage lautet dann "Kann die Last von CPU 3 von X zurückgeben. Das Ausführen von
    auf CPU B folgt einer Last aus derselben Variablen, die auf CPU A ausgeführt wird (und
    CPU A hat ursprünglich nicht den von ihm gelesenen Wert gespeichert). Auf
    Multicopy-Atomic-Systemen muss die Last von CPU B entweder denselben Wert zurückgeben. Der Linux -Kernel
    erfordert jedoch keine Systeme für Multikopy -Atomic. Wenn im Beispiel die Last von CPU 2 von X von x zurückgibt, muss die Last von 1 und CPU 3 von Y auch zurückkehren. Multicopy-Atomizität, es ist noch schwächer. Die Anforderung ist, dass ein indirekter Pfad von Thread1 zu Thread3 über die Weiterleitung durch Thread2 nicht schneller sein kann als der direkte Pfad von Thread1 zu Thread3. zu sagen: < /p>

    Diese Substitution ermöglicht es nicht multikopy Atomizität. /> Der wichtigste Punkt ist, dass die Datenabhängigkeit von CPU 2 jedoch nicht garantiert, dass die CPU 1 -Store der CPU 1 bestellt. Wenn dieses Beispiel auf einem nicht-multikopy-atomarischen System ausgeführt wird, bei dem CPUs 1 und 2 einen
    -Puffer oder ein Cache-Maßstab teilen, kann CPU 2 einen frühen Zugriff auf die
    -Schrats von CPU 1 haben. Allgemeine Hindernisse sind daher erforderlich, um sicherzustellen, dass alle CPUs
    auf die kombinierte Reihenfolge mehrerer Zugriffe vereinbar sind. Unter der Annahme, dass Thread1 auf CPU 1, Thread2 auf CPU 2 und Thread3 auf CPU 3 liegt, wenn Thread2 lautet (x == 1), beweist dies, dass der Wert mindestens in ihrem freigegebenen Speicherpuffer liegt (gemeinsam mit Thread1 und Thread2, aber nicht Thread3). Dann schreibt Thread2 y = 1, aber der Wert kann nur bei Thread3 sichtbar werden, wenn der gemeinsame Speicherpuffer von Thread1 und Thread2 gespült wurde. Da der Store -Puffer bereits den neuen Wert von x enthielt, kann der neue Wert von Y nicht sichtbar werden, ohne auch den neuen Wert von X zu Thread3 zu gleichzeitig sichtbar zu machen. Vor dem neuen Wert von x ist sichtbar für Thread3, und Sie benötigen eine vollständige Speicherbarriere in Thread2, um dies zu verhindern. Ich frage mich also, ob es immer gelten könnte oder ob es eine echte Hardware -Architektur gibt, die ein kontrolliertes Beispiel ist und die Eigenschaft verletzt? Verwenden der Dokumentation zur Speicherbestellung. Andernfalls sollte es sich um eine Hardware- und Cache-Kohärenz-Protokolldiskussion handeln. Erklären Sie, warum keine aktuelle Hardware gegen die Eigenschaft verstößt, und nach welchem Mechanismus dies erreicht wird. Erklären Sie, was Hardwarearchitektur und Cache-Kohärenz-Protokoll gegen die Eigenschaft verstoßen, und nach welchem Mechanismus dies geschieht. Gehen Sie durch das Beispiel, um zu zeigen, wo es schief geht. />https://git.kernel.org/pub/scm/linux/ke ... .txt#n1370

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post