Зачем использовать _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?
Может ли это иметь небольшое преимущество в производительности? Историческая катастрофа?
Ответы
Ответ 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
, чтобы проверить, все ли определено.]