Чтение нескольких файлов в несколько потоков с помощью C #, медленно! - PullRequest
7 голосов
/ 16 ноября 2009

У меня есть процессор Intel Core 2 Duo, и я читал 3 файла с моего диска C: и показывал некоторые совпадающие значения из файлов в EditBox на экране. Весь процесс занимает 2 минуты. Затем я подумал об обработке каждого файла в отдельном потоке, а затем весь процесс занимает 2,30 минуты !!! т.е. на 30 секунд больше, чем однопоточная обработка.

Я ожидал обратного! Я могу видеть оба графика в истории использования процессора. Кто-нибудь, пожалуйста, объясните мне, что происходит? вот мой фрагмент кода.

 foreach (FileInfo file in FileList)
{

   Thread t  = new Thread(new ParameterizedThreadStart(ProcessFileData));
   t.Start(file.FullName);  

}

, где processFileData - метод обработки файлов.

Спасибо!

Ответы [ 4 ]

11 голосов
/ 16 ноября 2009

Корень проблемы в том, что файлы находятся на одном и том же диске, и, в отличие от вашего двухъядерного процессора, ваш жесткий диск может одновременно выполнять только одну операцию.

Если вы читаете два файла одновременно, головки дисков будут переходить от одного файла к другому и обратно. Учитывая, что ваш жесткий диск может прочитать каждый файл примерно за 40 секунд, теперь у него есть дополнительные накладные расходы на перемещение своей дисковой головки между тремя отдельными файлами много раз во время чтения.

Самый быстрый способ прочитать несколько файлов с одного жесткого диска - это сделать все это в одном потоке и читать их один за другим. Таким образом, головка перемещается только один раз за чтение файла (в самом начале), а не несколько раз за чтение.

Чтобы оптимизировать этот процесс, вам нужно либо изменить свою логику (вам действительно нужно прочитать все содержимое всех трех файлов?). Или купите более быстрый жесткий диск / поместите 3 файла на три разных жестких диска и используйте многопоточность / используйте raid.

3 голосов
/ 16 ноября 2009

Если вы читаете с диска, используя несколько потоков, то головки диска отскакивают от одной части диска к другой, поскольку каждый поток читает с другой части диска. Это может значительно снизить пропускную способность, как вы уже видели.

По этой причине, на самом деле, часто лучше, чтобы все обращения к диску проходили через один поток, чтобы минимизировать количество обращений к диску.

Если ваша задача связана с вводом-выводом и если она должна часто выполняться, вы можете посмотреть на инструмент, подобный «contig», чтобы убедиться, что расположение ваших файлов на диске оптимизировано / непрерывно.

1 голос
/ 16 ноября 2009

Если ваша обработка в основном связана с вводом-выводом и ЦП, имеет смысл, что это займет то же время или даже больше.

Как вы сравниваете эти файлы? Вы должны подумать, что является узким местом вашего приложения? IO выход / вход, процессор, память ...

Многопоточность интересна только для обработки, связанной с процессором. то есть сложный расчет, сравнение данных в памяти, сортировка и т.д ...

0 голосов
/ 16 ноября 2009

Поскольку ваш процесс связан с вводом-выводом, вы должны позволить ОС выполнять ваши потоки за вас. Посмотрите на FileStream.BeginRead () для примера того, как поставить в очередь ваши чтения. Ваш метод EndRead () может ускорить ваш следующий запрос для чтения следующего блока данных, указывающего на себя, для обработки каждого последующего завершенного блока.

Кроме того, когда вы создаете дополнительные потоки, ОС должна управлять несколькими потоками. И если для обработки завершенного чтения выбрано другое ЦПУ, вы потеряли все кэширование ЦП, где возникла ваша нить.

Как вы обнаружили, вы не можете "ускорить" приложение, просто добавив темы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...