Подтвердить что ты не робот

Зачем использовать _mm_malloc? (в отличие от _aligned_malloc, alligned_alloc или posix_memalign)

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

С11

void * aligned_alloc (size_t alignment, size_t size)

POSIX

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

Окна

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 также предоставляет другой набор памяти API-интерфейсы. Программисты C/С++ могут использовать _mm_malloc и _mm_free для выделения и свободные выровненные блоки памяти. Например, следующее оператор запрашивает 64-байтовый выровненный блок памяти для 8 с плавающей запятой элементы.

farray = (float *) __ mm_malloc (8 * sizeof (float), 64);

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Если автор функции aligned-allocate знает, как реализованы malloc и free, часто можно будет координировать проектирование всех функций распределения/освобождения, чтобы free мог различать все виды распределения и обрабатывать их надлежащим образом. Однако ни одна реализация с выравниванием-распределением не будет использоваться во всех реализациях 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, чтобы проверить, все ли определено.]