Memcpy вне чипа? - PullRequest
       36

Memcpy вне чипа?

6 голосов
/ 13 августа 2011

Я сегодня профилировал программу на работе, которая выполняет большую часть буферизованной сетевой активности, и эта программа проводила большую часть своего времени в memcpy, просто перемещая данные назад и вперед между сетевыми буферами, управляемыми библиотекой, и своими собственными внутренними буферами.1001 *

Это заставило меня задуматься, почему у Intel нет инструкции «memcpy», которая позволяет самой ОЗУ (или аппаратной памяти вне ЦП) перемещать данные, не затрагивая ЦП?Поскольку каждое слово должно быть полностью передано в ЦП, а затем снова вытолкнуто обратно, когда все это может быть выполнено асинхронно самой памятью.

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

Ответы [ 3 ]

2 голосов
/ 14 августа 2011

Это большая проблема, которая включает в себя эффективность сетевого стека, но я буду придерживаться вашего конкретного вопроса инструкции. То, что вы предлагаете, - это асинхронная неблокирующая инструкция копирования, а не синхронная блокировка memcpy, доступная сейчас с использованием «rep mov».

Некоторые архитектурные и практические проблемы:

1) Неблокирующая memcpy должна потреблять некоторый физический ресурс, такой как механизм копирования, с временем жизни, потенциально отличающимся от соответствующего процесса операционной системы. Это довольно неприятно для ОС. Предположим, что поток A запускает memcpy непосредственно перед переключением контекста на поток B. Поток B также хочет сделать memcpy и имеет гораздо более высокий приоритет, чем A. Должен ли он ждать завершения работы memcpy потока A? Что если memcpy А был длиной 1000 ГБ? Предоставление большего количества механизмов копирования в ядре откладывает, но не решает проблему. По сути это нарушает традиционный цикл квантования времени и планирования ОС.

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

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

4) Инструкция asynch memcpy должна возвращать какой-то токен, который идентифицирует копию для последующего использования, чтобы спросить, выполняется ли копия (требующая другой инструкции). Учитывая маркер, ядро ​​должно было бы выполнить какой-то сложный контекстный поиск относительно этой конкретной ожидающей или находящейся в полете копии - такие операции лучше обрабатываются программным обеспечением, чем основным микрокодом. Что делать, если ОС нужно убить процесс и убрать все выполняемые и ожидающие операции memcpy? Как ОС узнает, сколько раз процесс использовал эту инструкцию и какие соответствующие токены принадлежат какому процессу?

--- РЕДАКТИРОВАТЬ ---

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

1 голос
/ 14 августа 2011

Net Win?

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

Более тяжелый пользовательский контекст?

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

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

Наложение существующего состояния - это именно то, как работают команды перемещения строки: они сохраняют свои параметры в общих регистрах.Но если существующее состояние используется, тогда это состояние бесполезно во время операции, и можно также просто использовать инструкции перемещения строки, как на самом деле работают функции копирования памяти.

Или ресурс удаленного ядра?

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

Идея!Пусть этот суперскоростной процессор сделает это!

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

1 голос
/ 14 августа 2011

Передача из памяти в память раньше поддерживалась контроллером DMA в старых архитектурах ПК.Подобная поддержка существует и в других архитектурах сегодня (например, процессоры TI DaVinci или OMAP ).

Проблема заключается в том, что она снижает пропускную способность вашей памяти, что может быть узким местом во многих системах.Как подсказывает ответ srking, чтение данных в кэш ЦП и последующее их копирование может быть намного более эффективным, чем память в память DMA.Даже при том, что DMA может работать в фоновом режиме, будет конфликт шины с процессором.Нет бесплатных обедов.

Лучшее решение - это какая-то архитектура zero copy , в которой буфер распределяется между приложением и драйвером / оборудованием.То есть входящие сетевые данные считываются непосредственно в заранее выделенные буферы и не требуют копирования, а внешние данные считываются непосредственно из буферов приложения на сетевое оборудование.Я видел, как это делается во встроенных сетевых стеках в реальном времени.

...