Какую библиотеку или API следует использовать для реализации модуля ядра Linux, выполняющего асинхронный ввод-вывод?

Сначала я расскажу об окружении моего ПК, предыстории моего вопроса, моей проблеме, затем я объясню свой точный вопрос.

Окружающая среда:
ОС: Ubuntu 16.04
Ядро: 4.17.1
ЦП: i7-6700k
Память: 8 ГБ DRAM
Хранилище: SSD 120 ГБ

Предыстория:
я пытаюсь оптимизировать ядро ​​Linux для своего конкретного приложения. Ниже приведена абстрактная логика этого приложения.
1. Вызвать malloc, выделить пространство памяти, размер которого ровно 4 КБ (размер страницы)
2. Скопировать предопределенные данные (также, размер 4 КБ) в выделенное пространство памяти.< br> 3. Выполнение вычислений
4. Освобождение выделенного пространства памяти.
Эта последовательность повторяется примерно от нескольких тысяч до десяти тысяч раз в секунду. Поэтому я подумал, что копировать предопределенные данные в выделенное пространство памяти с помощью memcpy() тысячи раз в секунду очень неэффективно. Но я не могу исправить код этого приложения.

Моя проблема:
Я хочу делать эти копии асинхронно с помощью модуля ядра, используя как можно меньше циклов процессора. Итак, я пытаюсь реализовать модуль ядра, который асинхронно копирует эти предопределенные данные в свободные кадры страниц в ядре и управляет кадрами страниц пула, на которых есть предопределенные данные. Когда мое конкретное приложение запрашивает кадр страницы, мое ядро ​​​​выдает кадр страницы из этого пула.

Для асинхронного копирования данных я сначала рассматривал DMA, но Intel idma64 моего процессора не может асинхронно копировать данные из памяти в память. Теперь я пытаюсь скопировать эти данные из вторичного хранилища (SSD) в память. Я обнаружил, что в Linux есть библиотека для асинхронного ввода-вывода с именем libaio.

Мой вопрос:
1. Могу ли я использовать библиотеки libaio в модуле ядра? Если нет, то какую библиотеку или API мне нужно использовать для асинхронного копирования в моем модуле ядра?
2. Будет ли libaio (или что-то еще) действительно копировать без использования циклов ЦП?


person 양석우    schedule 24.06.2018    source источник
comment
Оставайтесь в пространстве пользователя. Используйте gprof или perf для профилирования вашего приложения, чтобы точно увидеть, на что тратится время. memcpy из 4 КБ на этом процессоре должно быть меньше микросекунды.   -  person Mike Andrews    schedule 24.06.2018
comment
Находятся ли предопределенные данные на жестком диске (в файле)? Если это так, используйте асинхронное чтение из файла. Если у вас есть предопределенные данные в ОЗУ, то не существует такой вещи, как асинхронное копирование из ОЗУ в ОЗУ: асинхронное означает отсутствие ожидания, если базовые операции ожидают (то есть не потребляют ЦП, а некоторые другие устройство). Но копирование из ОЗУ в ОЗУ выполняется только процессором.   -  person Tsyvarev    schedule 24.06.2018
comment
@MikeAndrews Спасибо за ваш комментарий. Я знаю, что memcpy не очень дорогая работа, но копирование 4 КБ данных в кеш более 10000 раз в секунду приведет к загрязнению кеша. И по многим другим причинам я должен это сделать.   -  person 양석우    schedule 25.06.2018
comment
@Tsyvarev Предопределенные данные находятся на жестком диске. И моя цель - скопировать эти данные в пустой фрейм страницы с минимальным потреблением циклов ЦП. Я подумал, что лучше загрузить эти данные в ОЗУ и выполнить копирование из ОЗУ в ОЗУ с помощью DMA, но мой компьютер не поддерживает копирование из ОЗУ в ОЗУ. Итак, я пытаюсь асинхронно скопировать предопределенные данные из файла на SSD. Итак, как я могу асинхронно прочитать файл в ядре? Блокирует ли ввод-вывод в ядре асинхронно? И означает ли асинхронное чтение в вашем комментарии копирование данных из хранилища в оперативную память?   -  person 양석우    schedule 25.06.2018
comment
Я не совсем понял: ваше приложение (описано 4 шагами) работает в пользовательском пространстве или в ядре? Если первое, то почему вы хотите прочитать файл в ядре? Если второе, то код ядра редко называют приложением. Также в ядре нет библиотек. Пожалуйста, уточните это.   -  person Tsyvarev    schedule 25.06.2018


Ответы (1)


Я не думаю, что вам нужно писать модуль ядра. Пул потоков пользовательского пространства из закрепленных потоков ЦП, работающих с набором карт памяти файлов, будет настолько эффективным, насколько это возможно реализовать. Просто будьте осторожны с «стрельбой TLB», то есть избегайте изменения адресного пространства процесса и используйте как можно больше виртуального адресного пространства для решения проблемы, чтобы избежать этого. Возможно, небольшой намек ядру на то, какие написанные страницы никогда больше не будут использоваться через madvise(), и вы должны быть оптимальны — достаточное количество потоков максимизирует глубину очереди на SSD, вы хотите стремиться к QD8 до QD16, и вы должен легко насыщать канал NVMe, сохраняя загрузку ЦП ниже 100%.

Все становится сложнее, если у вас много твердотельных накопителей, подключенных к NVMe, вам, возможно, придется подумать о замене Linux чем-то с более масштабируемым вводом-выводом хранилища, но здесь есть компромисс между пропускной способностью и масштабируемостью. Windows и FreeBSD будут лучше масштабироваться с большим количеством устройств, если вы правильно разделите работу, но Linux будет работать намного лучше с несколькими устройствами. Удачи!

person Niall Douglas    schedule 25.06.2018