2009-12-10 3 views
0

Я пытаюсь выжать максимум производительности из драйвера блока Linux для высококачественного устройства хранения. Одна из проблем, которая меня немного затормозила на данный момент, заключается в следующем: если пользовательская задача запускает операцию ввода-вывода (чтение или запись) на одном ЦП, а прерывание устройства происходит на другом ЦП, я беру на себя около 80 микросекунд задержки перед задача возобновляет выполнение.Почему блокировка ввода-вывода занимает слишком много времени при пересечении ЦП?

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

Я могу показать себе, что проблема возникает между вызовом bio_endio на одном CPU и задачей, перенесенной на другой ЦП. Если задача находится на одном процессоре, она запускается очень быстро, и если задача находится на другом физическом ЦП, она занимает намного больше времени - обычно около 80 микросекунд дольше в моей текущей тестовой системе (x86_64 на чипсете Intel 5520 [NUMA]).

Я могу мгновенно удвоить свое выступление, установив процесс и привязанность процессора IRQ к одному и тому же физическому процессору, но это не очень хорошее долгосрочное решение. Я бы предпочел получить хорошую производительность независимо от того, где я/Os. И у меня только один IRQ, поэтому я могу управлять только одним процессором за один раз - неважно, если многие потоки работают на многих процессорах.

Я вижу эту проблему на ядрах от 2.6.28 Centos 5.4 до основной линии 2.6.32.

Итак, вопрос в том, почему для возобновления пользовательского процесса требуется больше времени, если я позвоню bio_endio из другого ЦП? Это проблема планировщика? И есть ли способ устранить или снизить задержку?

ответ

0

Похоже, я неправильно понял проблему: она, похоже, связана с промахами в кеше; когда обработчики прерываний процессора не были процессором, который запустил i/o, процессор может использовать 100% -ное использование, а затем все замедляется, создавая впечатление, что между процессором происходит длинная задержка.

Спасибо всем за их идеи.

+0

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

+0

Нет замков, просто огромное количество ввода-вывода. И система NUMA, которая пропускает кросс-cpu, действительно дорогая. Большие переводы лучше, но иногда вам приходится брать то, что дает ядро ​​или приложение. –

1

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

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

Насколько я понимаю.

+0

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

1

Это может быть латентность, присущая выпуску IPI от CPU, который завершил биографию CPU, где задача запланирована - чтобы проверить это, попробуйте загрузить с idle=poll.

+0

Интересные мысли. Это дало мне небольшое повышение производительности (2-3%), но, похоже, не влияет на основную проблему (которая снижает производительность пополам). –

1

This patch просто отвечал на LKML, внедрение QUEUE_FLAG_SAME_CPU в слое блочного устройства, которое описывается как:

Добавить флаг, чтобы сделать запрос на полный центрального процессора, где представляется запрос. Флаг означает QUEUE_FLAG_SAME_COMP. По умолчанию выключено.

Это звучит, как это может быть только то, что вам нужно ...

+0

Да, это звучит неплохо. К сожалению, я использую make_request для перехвата bios, прежде чем они попадут в очередь, поэтому я не могу воспользоваться этим, но приятно знать, что люди ядра думают в этом направлении. Я должен посмотреть, как это реализовано, и посмотреть, есть ли хорошие идеи, которые стоит заимствовать. –