2008-08-12 24 views
25

Chciałbym zadać pytanie, a następnie podążać za jego własną odpowiedzią, ale zobacz także, jakie odpowiedzi mają inni ludzie.Jak uzyskać dobrą równoczesną wydajność odczytu z dysku

Mamy dwa duże pliki, które chcielibyśmy czytać jednocześnie z dwóch oddzielnych wątków. Jeden wątek będzie kolejno czytał plik A, podczas gdy drugi wątek będzie kolejno czytał plik B. Nie ma blokowania ani komunikacji między wątkami, obie sekwencyjnie czytają tak szybko, jak tylko mogą, a obie natychmiast odrzucają dane, które odczytali.

Nasze doświadczenia z tą konfiguracją w systemie Windows są bardzo słabe. Łączna przepustowość tych dwóch wątków jest rzędu 2-3 MiB/s. Wydaje się, że większość czasu spędzają na wyszukiwaniu w tył i w przód między dwoma plikami, prawdopodobnie po bardzo trudnym czytaniu.

Jeśli wyłączymy jeden z wątków i tymczasowo spojrzymy na wydajność pojedynczego wątku, otrzymamy znacznie lepszą przepustowość (~ 45 MiB/s dla tego komputera). Tak więc zła wydajność dwubajtowa jest artefaktem programu planującego dyski OS.

Czy jest coś, co możemy zrobić, aby poprawić wydajność jednoczesnego odczytu wątku? Być może za pomocą różnych interfejsów API lub w inny sposób modyfikując parametry programu planującego dysku OS.

Niektóre szczegóły:

Pliki są w kolejności 2 GiB każdym na maszynie z 2GiB RAM. Na potrzeby tego pytania uważamy, że nie są one buforowane i doskonale defragmentowane. Wykorzystaliśmy narzędzia do defragmentacji i zrestartowaliśmy system, aby to zagwarantować.

Nie używamy specjalnych API do odczytu tych plików. Zachowanie jest powtarzalne dla różnych standardowych interfejsów API, takich jak CreateFile, C's fopen Win32, C++ std :: ifstream, Java FileInputStream, itp.

Każdy wątek obraca się w pętli, wykonując połączenia z funkcją odczytu. Zmieniliśmy liczbę bajtów żądanych z API w każdej iteracji z wartości od 1KB do 128 MB. Zmiana tego nie przyniosła żadnego efektu, tak wyraźnie, ile system operacyjny odczytywał fizycznie po tym, jak każde szukanie dysku nie jest podyktowane tym numerem. Dokładnie tego należy się spodziewać.

Drastyczna różnica między wydajnością jednego i dwóch wątków jest powtarzalna w systemach Windows 2000, Windows XP (32-bit i 64-bit), Windows Server 2003, a także z macierzą RAID5 i bez niej.

Odpowiedz

10

Problem wydaje się być związany z polityką planowania we/wy systemu Windows. Zgodnie z tym, co znalazłem here, istnieje wiele sposobów, dla których O.S. aby zaplanować żądania dysków. Podczas gdy Linux i inni mogą wybierać między różnymi zasadami, zanim Windows Vista był zablokowany w jednej zasadzie: kolejka FIFO, gdzie wszystkie żądania, w których dzieli się na 64 KB bloków. Uważam, że ta zasada jest przyczyną problemu, którego doświadczasz: program planujący będzie łączyć żądania z dwóch wątków, powodując ciągłe wyszukiwanie między różnymi obszarami dysku.
Dobra wiadomość jest taka, że ​​zgodnie z here i here, Vista wprowadziła bardziej inteligentny program do planowania dysków, w którym można ustawić priorytet żądań, a także przydzielać minimalną liczbę błędów dla procesu.
Zła wiadomość jest taka, że ​​nie znalazłem sposobu na zmianę polityki dyskowej lub rozmiaru buforów w poprzednich wersjach systemu Windows. Ponadto, nawet jeśli podniesienie priorytetu we/wy dysku zwiększy wydajność w stosunku do innych procesów, nadal będą występować problemy z rywalizacją wątków.
Mogę zaproponować modyfikację oprogramowania poprzez wprowadzenie własnej polityki dostępu do dysku.
Na przykład, można użyć politykę jak to w swoim wątku B (podobny do gwintów A):

if THREAD A is reading from disk then wait for THREAD A to stop reading or wait for X ms 
Read for X ms (or Y MB) 
Stop reading and check status of thread A again 

Można użyć semaforów do sprawdzania stanu lub można użyć perfmon liczniki, aby uzyskać stan faktyczny kolejka dyskowa. Wartości X i/lub Y można również automatycznie dostroić, sprawdzając aktualne szybkości transferu i powoli je modyfikując, maksymalizując przepustowość, gdy aplikacja działa na różnych urządzeniach i/lub O.S. Można stwierdzić, że poziomy pamięci podręcznej, pamięci lub RAID wpływają na nie w taki czy inny sposób, ale dzięki auto-tuningowi zawsze uzyskasz najlepszą wydajność w każdym scenariuszu.

5

Chciałbym dodać kilka dodatkowych uwag w mojej odpowiedzi. Wszystkie inne systemy operacyjne inne niż Microsoft, które przetestowaliśmy, nie cierpią z powodu tego problemu. Linux, FreeBSD i Mac OS X (ten ostatni na innym sprzęcie) pogrążają się znacznie bardziej pod względem łącznej przepustowości podczas przechodzenia z jednego wątku na drugi. Linux na przykład ulegał degradacji z ~ 45 MiB/s do ~ 42 MiB/s. Te inne systemy operacyjne muszą odczytywać większe partie plików pomiędzy każdą próbą, a tym samym nie spędzać prawie całego swojego czasu czekając na dysku, by szukać.

Nasze rozwiązanie dla systemu Windows przesyła flagę FILE_FLAG_NO_BUFFERING do CreateFile i używa dużych (~ 16 MB) odczytów w każdym wywołaniu do ReadFile. Jest to nieoptymalne z kilku powodów:

  • Pliki nie są zapisywane w pamięci podręcznej po przeczytaniu w ten sposób, więc nie ma żadnych zalet, które zwykle daje buforowanie.
  • Ograniczenia podczas pracy z tą flagą są znacznie bardziej skomplikowane niż normalne czytanie (wyrównanie buforów odczytu do granic stron itp.).

(Jako ostatnia uwaga. Czy to wyjaśnić dlaczego wymieniając pod Windows jest tak piekielny? Ie, Windows nie jest w stanie robić IO do wielu plików jednocześnie z każdej sprawności, więc podczas wymiany wszystkie inne operacje IO są zmuszeni być nieproporcjonalnie powolny)


Edycja dodać kilka dalszych szczegółów albowiem Dean.

oczywiście w poprzek tych różnych konfiguracjach sprzętowych surowe dane uległy zmianie (czasem znacznie). Problemem jest jednak konsekwentna degradacja wydajności, której doświadcza tylko system Windows przechodząc z jednego wątku na drugi. Oto podsumowanie badanych maszyn:

  • kilku stacjach roboczych Dell (Intel Xeon) w różnym wieku z systemem Windows 2000, Windows XP (32-bitowy) i Windows XP (64-bitowy) z pojedynczego dysku.
  • Serwer Dell 1U (Intel Xeon) z systemem Windows Server 2003 (64-bitowy) z RAID 1 + 0.
  • Stacja robocza HP (AMD Opteron) z systemem Windows XP (64-bit) i Windows Server 2003 oraz sprzętowa karta RAID 5.
  • Komputer domowy bez marki (AMD Athlon64) z systemem Windows XP (32-bitowy), FreeBSD (64-bitowy) i Linux (64-bitowy) z pojedynczym dyskiem.
  • Mój domowy MacBook (Intel Core1) z systemem Mac OS X, jednym napędem SATA.
  • Mój dom Koolu Komputer z systemem Linux. Ogromnie słabe w porównaniu do innych systemów, ale udowodniłem, że nawet ten komputer może lepiej radzić sobie z serwerem Windows z RAID5 podczas odczytu wielowątkowych dysków.

Wykorzystanie procesora we wszystkich tych systemach było bardzo niskie podczas testów, a antywirus został wyłączony.

Zapomniałem wspomnieć wcześniej, ale wypróbowaliśmy również normalne API Win32 CreateFile z zestawem flag FILE_FLAG_SEQUENTIAL_SCAN. Ta flaga nie naprawiła problemu.

+0

Witamy w firmie Microsoft. –

0

Chciałbym utworzyć pewien rodzaj blokady bezpieczeństwa wątku w pamięci. Każda nić może czekać na blokadę, aż będzie wolna. Kiedy blokada stanie się wolna, weź blokadę i odczytaj plik przez określony czas lub określoną ilość danych, a następnie zwolnij blokadę dla innych oczekujących wątków.

1

Wydaje się dziwne, że nie widzisz różnicy między szeroką gamą wersji systemu Windows i niczym pomiędzy jednym dyskiem a spakowaniem sprzętu-5.

To tylko "przeczucie", ale to sprawia, że ​​wątpię, że jest to naprawdę prosty problem z wyszukiwaniem. Inne niż OS X i Raid5, wszystko to wypróbowano na tej samej maszynie - czy próbowałeś innej maszyny? Czy podczas tego testu użycie procesora w zasadzie wynosi zero?

Jaka jest najkrótsza aplikacja, którą można napisać, która pokazuje ten problem? - Byłbym zainteresowany wypróbowaniem go tutaj.

+0

dla pojedynczego napędu vs raid5: jeśli czytasz sekwencyjne dane z dwóch wystarczająco dużych plików, nie możesz uniknąć * wszystkich * głowic dysków szukających tam iz powrotem; rozmiar paska wynosi zwykle 16-128kiB, więc aby odczytać 1 MB danych, potrzebujesz wszystkich (lub większości) głów, aby tam szukać. – tzot

0

Paul - zobaczyłem aktualizację. Bardzo interesujące.

Interesujące byłoby wypróbowanie tego na Vista lub Win2008, ponieważ ludzie wydają się zgłaszać znaczące usprawnienia I/O w niektórych okolicznościach.

Moja jedyna sugestia dotycząca innego interfejsu API to wypróbowanie mapowania plików w pamięci - czy próbowałeś tego? Niestety przy 2 GB na plik, nie będziesz w stanie mapować wielu całych plików na komputerze 32-bitowym, co oznacza, że ​​nie jest to tak banalne, jak mogłoby być.

+0

idąc do takich rozszerzeń tylko po to, aby coś działało na Windowsie, po prostu popieram przeniesienie jego procesu do Linuksa. jaki jest koszt każdego rozwiązania? szczerze... –

Powiązane problemy