Можно ли использовать потоки для ускорения чтения файлов? - PullRequest
17 голосов
/ 16 июня 2010

Я хочу прочитать файл как можно быстрее (40 тыс. Строк) [Редактировать: остальное устарело].

Edit: Andres Jaan Tack предложил решение, основанное на одном потоке на файл, и я хочу быть уверен, что получил (таким образом, это самый быстрый способ):

  • Один поток на каждый файл записи читает его целиком и хранит его содержимое в связанном контейнере (-> столько контейнеров, сколько имеется файлов записи)
  • Один поток вычисляет линейную комбинацию каждой ячейки, прочитанной входными потоками, и сохраняет результаты в выходном контейнере (связанном с выходным файлом).
  • Один поток записывает блоком (каждые 4 КБ данных, т.е. около 10 строк) содержимое выходного контейнера.

Должен ли я сделать вывод, что я не должен использовать файлы m-mapped (поскольку программа находится в режиме ожидания в ожидании данных)?

Спасибо заранее.

С уважением,

Мистер мистер.

Ответы [ 6 ]

26 голосов
/ 16 июня 2010

Ваш вопрос стал немного глубже, когда вы задали вопрос дальше. Я постараюсь охватить все ваши варианты ...

Чтение Один Файл: Сколько потоков?

Использовать одну нить.

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

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

Примечание: это еще до того, как вы добавите стоимость настройки потоков и всего остального. Это тоже чего-то стоит, но в основном это ничто по сравнению со стоимостью более блокирующего доступа к диску.

Чтение нескольких файлов: сколько потоков?

Используйте столько потоков, сколько у вас есть файлов (или некоторое разумное число).

Предварительная выборка файла выполняется отдельно для каждого открытого файла. Как только вы начнете читать несколько файлов, вы должны читать из нескольких из них параллельно. Это работает, потому что диск I / O Scheduler будет пытаться выяснить самый быстрый порядок, в котором можно прочитать все из них. Часто в ОС и на жестком диске есть планировщик дисков. Между тем, предварительный сборщик все еще может выполнять свою работу.

Чтение нескольких файлов параллельно всегда лучше , чем чтение файлов по одному. Если вы читаете их по одному, ваш диск будет простаивать между предварительными выборками; это ценное время, чтобы прочитать больше данных в память! Единственный путь, по которому вы можете пойти не так, - это если у вас слишком мало оперативной памяти для поддержки большого количества открытых файлов; это больше не распространено.

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

Объединение n файлов в один.

Обработка и создание выходных данных из нескольких потоков могут работать, но это зависит от того, как вам нужно их объединять. В любом случае вам нужно быть осторожным с тем, как вы синхронизируете потоки, хотя, безусловно, есть несколько относительно простых безблокировочных способов сделать это.

Однако нужно искать одну вещь: не беспокойтесь о записи файла небольшими (<4K) блоками. Соберите <em>не менее 4K данных за раз , прежде чем звонить write(). Кроме того, поскольку ядро ​​заблокирует файл при его записи, не вызывайте write() из всех ваших потоков вместе; все они будут ждать друг друга, а не обрабатывать больше данных.

18 голосов
/ 16 июня 2010

[Редактировать: исходный вопрос, заданный, если запуск до 40 000 потоков ускорит чтение файла]

То, что вы предлагаете, скорее всего замедлит доступ из-за накладных расходов на создание потоков и переключение контекста.Другие потоки помогают, только если вы

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

2), и другие потоки могут работать, ожидая, пока другие разблокируют

3) у вас есть очень умный алгоритм, который использует поведение кеша

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

4 голосов
/ 16 июня 2010

В отличие от других читателей, я считаю, что теоретически может принести пользу, даже если вы работаете в системе SP (однопроцессорный).Однако я бы никогда не сделал это для строк длиной 40 КБ (при условии, что вы говорите о линиях нормального размера).

Они - ключ ответа Амардипа, где он / она говорит, что создание потоков полезно, когда поток становится заблокирован по некоторым причинам.

Теперь, как "работают" сопоставленные файлы?При первом обращении к странице памяти в этом регионе процессор генерирует ошибку страницы.ОС загружает содержимое файла (это включает доступ к диску) на страницу памяти.Затем выполнение возвращается в ваш поток.

Я также считаю, что после сбоя страницы ОС заполняет кучу последовательных страниц, а не только одну.

Теперь важно то, что во время сбоя страницыобработка вашей темы приостановлена ​​.Также в этот период ЦП не загружается (кроме того, что могут делать другие процессы).

Так что, если вы посмотрите на шкалу времени, вы увидите период из двух разделов: один, где загружен ЦП (здесьВы читаете содержимое страницы и выполняете некоторую обработку), и тот, в котором ЦП почти простаивает и ввод / вывод на диске выполняется.

С другой стороны, вы можете создать несколько потоков, каждый из которыхназначен для чтения другой части файла.Вы получаете два эффекта:

  1. Другой поток может загрузить ЦП (или несколько ЦП, если система MP), когда один из них заблокирован вводом / выводом.

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

Например, при чтении множества различных секторов изHD-накопитель, который вы действительно можете прочитать все за один оборот диска.

PS

И, конечно, я никогда не думал делать это для 40K строк.Затраты на создание потоков, ожидание их завершения, переключение контекста, компиляцию логики, обработку ошибок / сбоев и т. Д.

Я бы попытался сделать это для файла размером не менее десятков МБ.

4 голосов
/ 16 июня 2010

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

1 голос
/ 16 июня 2010

Это проблема детализации. У вас небольшой файл и очень мало обработки. Один поток может, вероятно, поглотить весь файл за один отрезок времени и обработать его в следующем. Две темы будут хуже, чем одна. Прежде чем рассматривать параллелизм в качестве решения для повышения производительности, необходимо выполнить гораздо более сложную задачу.

0 голосов
/ 16 июня 2010

Я так думаю.

У вас 8 ядер, так что сделайте 8 потоков. Пусть каждый поток разбирает один блок файла. Таким образом, вам нужно получить размер устройства / дискового блока. Когда блок был проанализирован потоком, пусть поток анализирует новый, еще не «назначенный» потоку.

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

Но это может быть превращено в конкурс. Ничто не сравнится с реальными живыми пробежками! и люди покажут тебе! :) найди подходящую цену!

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