Зачем использовать mm malloc? (в отличие от выравниваются Танос, ассоциировала к alloc, или memalign в POSIX )

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

C11

void * aligned_alloc (size_t alignment, size_t size)

POSIX

int posix_memalign (void **memptr, size_t alignment, size_t size)

Windows

void * _aligned_malloc(size_t size, size_t alignment);

и, конечно, это также всегда возможность выравнивания вручную.

Intel предлагает другой вариант.

корпорация Intel

void* _mm_malloc (int size, int align)
void _mm_free (void *p)

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

https://software.intel.com/en-us/articles/memory-management-for-optimal-performance-on-intel-xeon-phi-coprocessor-alignment-and

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

int posix_memalign (void * * memptr, size_t align, size_t size);

компилятор Intel также предоставляет другой набор выделения памяти Апис. Программисты C / C++ могут использовать _mm_malloc и _mm_free для выделения и бесплатно выровненные блоки памяти. Например, следующее оператор запрашивает 64-байтовый выровненный блок памяти для 8 с плавающей запятой элементы.

farray = (float *)_ _ mm _ malloc(8*sizeof(float), 64);

память, выделенная с помощью _mm_malloc, должна быть освобождена с помощью _mm_free. Вызов free в памяти, выделенной _mm_malloc, или вызов _mm_free в памяти, выделенной malloc, приведет к непредсказуемому поведению.

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

3 ответов


компиляторы Intel поддерживают операционные системы POSIX (Linux) и non-POSIX (Windows), следовательно, не могут полагаться ни на POSIX, ни на функцию Windows. Таким образом, было выбрано специфичное для компилятора, но ОС-агностическое решение.

C11-отличное решение, но Microsoft еще не поддерживает C99, поэтому кто знает, будут ли они когда-либо поддерживать C11.

обновление: в отличие от функций распределения C11/POSIX/Windows, встроенные ICC включают функцию освобождения. Это позволяет этому API использовать отдельный менеджер кучи от менеджера по умолчанию. Я не знаю, действительно ли/когда это происходит, но может быть полезно поддерживать эту модель.

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


можно взять существующий компилятор C, который в настоящее время не использует идентификаторы _mm_alloc и _mm_free и определить функции с теми именами, которые будут вести себя так, как требуется. Это может быть сделано либо с помощью_mm_alloc функция как обертка на malloc() который запрашивает слегка негабаритное распределение и создает указатель на первый соответствующим образом выровненный адрес внутри него, который составляет по крайней мере один байт с самого начала, и сохраняет количество байтов, пропущенных сразу до этого адреса, или _mm_malloc запрос большие куски памяти из malloc() и затем распределить их по частям. В любом случае, указатели возвращаются _mm_malloc() не было бы указателей, что free() обычно знает, как что-то делать с; вызов _mm_free будет использовать байт, непосредственно предшествующий распределению, в качестве помощи для поиска реального начала распределения, полученного от malloc, а потом проходят, Что делать free.

если функция aligned-allocate разрешена использовать внутренности malloc и free функции, однако, которые могут исключить потребность для дополнительного слоя оборачивать. Можно написать _mm_alloc()/_mm_free() функции, которая оборачивает malloc/free ничего не зная о своих внутренних органах, но это требует этого _mm_alloc() держите бухгалтерскую информацию, которая отделена от того, что используется malloc/free.

если автор функции aligned-allocate знает, как malloc и free несколько реализовано, часто можно будет координировать дизайн всех функций распределения / свободных так, что free может различать все виды распределений и обрабатывать их соответствующим образом. Ни одна реализация aligned-allocate не будет использоваться для всех malloc/free однако реализаций.

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

#define a_alloc(align,sz) _mm_alloc((align),(sz))
#define a_free(ptr)  _mm_free((ptr))

на компиляторы, которые поддерживают это, или

static inline void *aa_alloc(int align, int size)
{
  void *ret=0;
  posix_memalign(&ret, align, size); // Guessing here
  return ret;
}
#define a_alloc(align,sz) aa_alloc((align),(sz))
#define a_free(ptr)  free((ptr))

на системах Posix и т. д. Для каждой системы должно быть возможно определить макросы или функции, которые дадут необходимое поведение [я думаю, что, вероятно, лучше использовать макросы последовательно, чем иногда использовать макросы и иногда функции, чтобы разрешить #if defined macroname чтобы проверить, определены ли вещи еще].


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

Я предполагаю, что в отличие от использования posix_memalign, ему не нужно чрезмерно выделять, чтобы гарантировать выравнивание, вместо этого он использует отдельный распределитель с учетом выравнивания. Это позволит сэкономить память при выделении различных типов с выравниванием выравнивание по умолчанию (обычно 8 или 16 байт).