Подтвердить что ты не робот

Можно ли использовать потоки для ускорения чтения файлов?

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

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

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

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

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

С уважением,

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

4b9b3361

Ответ 1

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

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

Используйте один поток.

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

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

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

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

  • У другого потока есть возможность загрузить CPU (или несколько процессоров, если система MP), когда один заблокирован с помощью ввода-вывода.

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

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

P.S.

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

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

Ответ 5

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

Ответ 6

Я так думаю.

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

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

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