2009-02-17 8 views
6

Na maszynie czterordzeniowej rozważam równoległość algorytmu C#/.NET, który polega na jednoczesnym odczytywaniu wielu wątków z małej tablicy int []. Do tej pory wydaje się działać dość dobrze, ale nie jestem pewien, gdzie jest określone, że jednoczesne odczyty na tablicy są bezpieczne dla wątków w .NET. Jakieś wskazówki?Równoczesny dostęp do odczytu w tablicy int []: Czy jest bezpieczny? Czy to szybko?

Następnie zastanawiam się również, czy to podejście jest naprawdę skuteczne? Czy są sytuacje, w których lepiej jest duplikować dane wejściowe dla każdego wątku, tak aby nie było żadnych jednoczesnych odczytów, a każda tablica (może?) Otrzymuje możliwość buforowania w pobliżu procesora koligacji?

Jakieś przemyślenia na temat najlepszych praktyk w odniesieniu do procesorów wielordzeniowych?

Odpowiedz

9

W twoim przypadku współbieżne odczyty z twojej tablicy będą bezpieczne dla wątków.

Jeśli chodzi o efektywność algorytmów, w zależności od rozmiaru macierzy, jeśli będzie pasował do pamięci podręcznej, może się okazać, że zyski z doskonałej wydajności są efektywne, ponieważ multicores skutecznie "walczą" o pamięć podręczną w procesorze. Jeśli będą walczyć o wypełnienie pamięci podręcznej tymi samymi informacjami, będą dzielić się znaczeniem większej liczby trafień w pamięci podręcznej i lepszej wydajności.

Zakładając, że tablica pasuje do pamięci podręcznej ...

18

Nie sądzę, aby wystąpił problem z równoczesnymi odczytami. Może to być problematyczne, jeśli istnieją jednoczesne komunikaty , które zapisują.

Dane trwałe są z natury bezpieczne dla wątków.

+0

Całkowicie się z tobą zgadzam, że niezmienne dane są bezpieczne dla wątków. Czasami jednak trudno jest określić, czy dane się nie zmienią. Na przykład pozorna operacja odczytu (lub powiedzmy "metoda zapytania") na obiekcie może spowodować wewnętrzne zapisanie. Zawsze musisz być na poszukiwania. Jednak z tablicami: odczytywanie tablicy z pewnością tego nie zmieni. – Steven

+1

@Steven zgadzają się, że nie zawsze można stwierdzić, czy coś jest niezmienne. Ale myślę, że twój przykład to po prostu zły projekt. Uważam, że niezmienne dane (zwłaszcza gdy są udostępniane) powinny być wyraźnie zaprojektowane jako takie. –

+0

@Marthinho: Nie masz pojęcia, jaki zły projekt byłam świadkiem w mojej karierze :-) To mnie kompulsywny, podejrzany programista. Nie ufam nikomu, nawet sobie :-) Niemniej zgadzam się ze wszystkim, co tu powiedziałeś. – Steven

4

Nie ma powodu, aby nie czytać zawartości tablicy jednocześnie, zakładając, że treść nigdy się nie zmieni. Nie ma problemu z współbieżnością, więc nie trzeba kopiować.

Wątpię, czy jest wiele rzeczy, które możesz zrobić, aby przyspieszyć.

3

Nie powinno ci to przeszkadzać. Jednoczesne czytanie nie stanowi problemu. Dowolna liczba wątków może jednocześnie odczytać tę samą pamięć.

2

Bezpieczeństwo wątków jest problemem tylko podczas aktualizacji danych. Jeśli masz wiele równoczesnych wątków, to tablica, którą będziesz musiał zawijać aktualizacje (i odczytuje, czy aktualizacje nie są atomowe) w mechanizmie synchronizacji. W przypadku struktury danych tylko do odczytu współbieżność nie jest problemem.

+0

Niekoniecznie. W tablicy nie ma problemu, ale w kolekcjach odczyt może nie być w ogóle bezpieczny dla wątków. – Spence

1

Operator przypisania nie jest bezpieczny dla wątków.

Oznacza to, że jeśli twoje wątki odczytują tylko tablicę - jeśli tablica została zainicjowana podczas uruchamiania programu i się nie zmienia - to jesteś bezpieczny.

Jednakże, jeśli istnieje pisarz, który pisze nowe wartości, jesteś podatny na warunki wyścigu.

Podstawową kwestią jest to; czytnik zaczyna czytać liczbę całkowitą. Wartość jest ładowana z pamięci do rejestru. W tym momencie czytelnik się zamienia. Pisarz aktualizuje następnie wartość w pamięci. Czytnik następnie wraca z powrotem i działa na wartość, którą załadował - co nie jest już poprawne.

Oznacza to, że rzeczy takie jak if() nie działają niezawodnie. Na przykład,

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

może wywołać, gdy wartość w pamięci z int_array[5] już 10.

wierzę w C# jest, trzeba mieć dostęp do Interlocked*() wywołań funkcji, takich jak InterlockedCompareAndSwap(). Pozwoli to na łatwe osiągnięcie bezpieczeństwa gwintu w tym przypadku.

Powiązane problemy