2009-02-17 3 views
6

Auf einer Quad-Core-Maschine, ich erwäge die Parallelisierung von C# /. NET-Algorithmus, die mehrere Threads das kleine int [] -Array gleichzeitig lesen. Bisher scheint es recht gut zu funktionieren, aber ich bin mir nicht sicher, wo angegeben wird, dass gleichzeitige Lesevorgänge in einem Array in .NET Thread-sicher sind. Irgendwelche Zeiger?Gleichzeitige Lesezugriff auf ein int [] Array: Ist es sicher? Ist es schnell?

Dann frage ich mich auch, ob dieser Ansatz wirklich effizient ist? Gibt es Situationen, in denen es besser ist, die Eingabedaten für jeden Thread zu duplizieren, so dass es kein gleichzeitiges Lesen gibt und jedes Array (vielleicht?) Die Gelegenheit erhält, in der Nähe der Affinitäts-CPU zwischengespeichert zu werden?

Irgendwelche Gedanken zu den Best Practices in Bezug auf Multicore-CPUs?

Antwort

9

In Ihrem Fall sind gleichzeitige Lesevorgänge über Ihr Array threadsicher.

Für Ihre Algorithmen Effektivität, abhängig von der Größe Ihres Arrays, wenn es in den Cache passt, können Sie sehen, ausgezeichnete Leistungssteigerungen, wie die Multicores effektiv "kämpfen" für den Cache in der CPU. Wenn sie kämpfen, um den Cache mit den gleichen Informationen zu füllen, teilen sie mehr Cachetreffer und bessere Leistung.

Unter der Annahme, dass Ihr Array in die Cache paßt ...

18

Ich glaube nicht, dass es ein Problem mit gleichzeitigem Lesen gibt. Es könnte jedoch problematisch sein, wenn gleichzeitig schreibt.

Unveränderbare Daten sind inhärent Thread-sicher.

+0

Ich stimme Ihnen von ganzem Herzen zu, dass unveränderliche Daten Thread-sicher sind. Manchmal ist es jedoch schwierig festzustellen, ob sich die Daten nicht ändern. Zum Beispiel kann eine augenscheinliche Leseoperation (oder, sagen wir mal, eine Abfragemethode) für ein Objekt intern einen Schreibvorgang verursachen. Da muss man immer auf der Hut sein. Bei Arrays jedoch: Das Lesen des Arrays wird es definitiv nicht ändern. – Steven

+1

@Steven stimmen zu, dass Sie nicht immer wissen können, ob etwas unveränderlich ist. Aber ich denke, dein Beispiel ist einfach schlechtes Design. Ich glaube, dass unveränderliche Daten (besonders wenn sie geteilt werden) ausdrücklich als solche entworfen werden sollten. –

+0

@Marthinho: Du hast keine Ahnung, wie viel schlechtes Design ich in meinem Träger gesehen habe :-) Es hat mich zu einem zwanghaften, verdächtigen Entwickler gemacht. Ich vertraue niemandem, nicht einmal ich selbst. Trotzdem stimme ich allem zu, was Sie hier gesagt haben. – Steven

4

Es gibt keinen Grund, den Inhalt eines Arrays nicht gleichzeitig zu lesen, vorausgesetzt, dass der Inhalt sich nie ändert. Es gibt kein Concurrency-Problem, daher muss nicht kopiert werden.

Ich bezweifle, es gibt viel, was Sie tun können, um es auch schneller zu machen.

3

Es sollte Sie nicht stören. Gleichzeitiges Lesen ist kein Problem. Eine beliebige Anzahl von Threads kann denselben Speicher zur gleichen Zeit lesen.

2

Thread-Sicherheit ist nur ein Problem, wenn Sie Daten aktualisieren. Wenn Sie mehrere gleichzeitige Threads haben Aktualisierung das Array müssen Sie die Updates (und liest, wenn die Updates sind nicht atomare) in einem Synchronisationsmechanismus. Bei einer schreibgeschützten Datenstruktur ist die Nebenläufigkeit kein Problem.

+0

Nicht unbedingt. In einem Array ist dies kein Problem, aber in Sammlungen sind Lesevorgänge möglicherweise gar nicht threadsafe. – Spence

3

Wenn .NET Performance und Parallelität auf dem Spiel steht, würde ich empfehlen, diesen speziellen Algorithmus in F #, um zu versuchen zu schreiben. Der F # -Compiler generiert .NET code that has 2-6 better performance.

+0

der Link ist kaputt – mcmillab

1

Der Zuweisungsoperator ist nicht threadsicher.

Das bedeutet, wenn Ihre Threads nur das Array lesen - wenn das Array beim Programmstart initialisiert wurde und sich nicht ändert - dann sind Sie sicher.

Wenn jedoch ein Schreiber existiert, der neue Werte schreibt, sind Sie anfällig für eine Race Condition.

Das Grundproblem ist das; Ein Leser beginnt eine ganze Zahl zu lesen. Der Wert wird aus dem Speicher in ein Register geladen. An diesem Punkt tauscht der Leser aus. Der Schreiber aktualisiert dann den Wert im Speicher. Der Leser schaltet sich dann wieder ein und wirkt auf den Wert, den er geladen hat - was nicht mehr stimmt.Das bedeutet, dass Dinge wie if() nicht zuverlässig funktionieren. Zum Beispiel

if(int_array[5] == 10) 
{ 
} 

auslösen kann, wenn der In-Memory-Wert von int_array[5] nicht mehr 10.

ich in C# glauben, sollten Sie den Zugriff auf die Interlocked*() Funktionsaufrufe haben, wie InterlockedCompareAndSwap(). Damit können Sie in diesem Fall problemlos die Fadensicherheit erreichen.

Verwandte Themen