Многопоточное чтение с диска? - программирование
Подтвердить что ты не робот

Многопоточное чтение с диска?

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

Можно ли многопоточно загружать эту загрузку?

Связано: все ли потоки одного процессора используют одно и то же устройство ввода-вывода для чтения с диска? В этом случае многопоточность не ускорит загрузку вообще - потоки будут просто ждать в очереди.

(В настоящее время я многопоточен с OpenMP.)

4b9b3361

Ответ 1

Да, это возможно. Однако:

Все ли потоки на одном процессоре используют одно и то же устройство ввода-вывода для чтения с диска?

Да. Головка чтения на диске. В качестве примера попробуйте копировать два файла параллельно, а не последовательно. Это займет значительно больше времени параллельно, поскольку ОС использует алгоритмы планирования, чтобы убедиться, что скорость ввода-вывода "справедливая" или равна двум потокам/процессам. Из-за этого считывающая головка будет перемещаться между различными частями диска, замедляя процесс вниз. Время фактического чтения данных довольно мало по сравнению с временем поиска, и когда вы читаете сразу две разные части диска, вы тратите большую часть времени на поиск.

Обратите внимание, что все это предполагает, что вы используете жесткий диск. Если вы используете SSD, это будет медленнее параллельно, но оно также не будет быстрее. Изменить: в соответствии с комментариями параллель на самом деле быстрее для SSD. С RAID ситуация усложняется, и (очевидно) зависит от того, какой тип RAID вы используете.

Это то, на что это похоже (я развернул круглый диск в прямоугольник, потому что круги ascii жесткие, и упростить структуру данных, чтобы упростить ее чтение):

Предположим, что файлы разделены некоторым пространством на тарелке:

|         |

Серийное чтение будет выглядеть так (* указывает на чтение)

space ----->
|        *|  t
|        *|  i
|        *|  m
|        *|  e
|        *|  |
|       / |  |
|     /   |  |
|   /     |  V
|  /      |
|*        |
|*        |
|*        |
|*        |

Пока параллельное чтение будет выглядеть как

|       \ |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|  \      |
|    \    |
|     \   |
|       \ |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|  \      |
|    \    |
|     \   |
|       \ |
|        *|

и т.д.

Ответ 2

Если вы делаете это в Windows, вы можете посмотреть в функции ReadFileScatter. Это позволит вам считывать несколько сегментов из файла в одном асинхронном вызове. Это позволит ОС лучше контролировать шею бутылки файла IO и, надеюсь, оптимизирует чтение.

Соответствующий вызов записи в Windows будет WriteFileGather.

Для UNIX вы смотрите readv и writev, чтобы сделать то же самое.

Ответ 3

Как упоминалось в других ответах, параллельное чтение может быть медленнее в зависимости от того, как файл физически хранится на диске. Поэтому, если голова должна двигаться на значительное расстояние, это может привести к фактическому замедлению. При этом, однако, существуют системы хранения, которые могут поддерживать многократное одновременное считывание и запись эффективно. Самый простой, который я могу себе представить, это SSD-диск. Я сам работал с великолепными системами хранения от IBM, которые могли выполнять одновременное чтение и запись без замедления. Поэтому предположим, что у вас есть такая файловая система и физическое хранилище, которое не замедлит параллельные чтения.

В этом случае параллельные чтения очень логичны. В общем, есть два способа добиться этого:

  • Если вы хотите использовать стандартную библиотеку C/С++ для выполнения ввода-вывода, то единственным вариантом, который у вас есть, является сохранение одного дескриптора открытого файла (дескриптора) в потоке. Это связано с тем, что указатель файла (который указывает, где читать или записывать из файла) хранится для каждого дескриптора. Поэтому, если вы пытаетесь читать одновременно из одного и того же дескриптора файла, у вас не будет никакого способа узнать, что вы на самом деле читаете.
  • Используйте API-интерфейс платформы для выполнения асинхронного (OVERLAPPED) ввода-вывода. В Windows вы используете функции WinAPI с тем, что называется OVERLAPPED IO. В Unix/Linux у вас есть posix AIO, хотя я понимаю, что его использование обескуражено, хотя я не видел удовлетворительного объяснения, почему это так.

Я сам реализовал оба подхода fd/thread как для linux, так и для windows, а также для подхода OVERLAPPED для Windows. Оба отлично работают.

Ответ 4

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

Ответ 5

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

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