Альтернатива ручному исправлению выравнивания данных sse2 на 16-байтовой границе
Есть ли альтернатива следующей ручной починке:
// excerpt adapted from SIMDTest in
// http://www.mccauslandcenter.sc.edu/mricro/obsolete/graphics/simdtest.zip
//
var
lAdblRAp, lArraySz, lAdblRA, Doublep: LongInt;
begin
// ...
GetMem(lAdblRAp,(lArraySz * SizeOf(Double)) + 32);
lAdblRA := Doublep((Integer(lAdblRAp) and $FFFFFFF0) + 16);
// ...
end;
Обратите внимание, что этот фрагмент кода встроен либо в процедуру, либо в функцию.
2 ответа
Стандартный способ - использовать диспетчер памяти, который выровняет блоки по 16-байтовым границам. FastMM сделает это, но вам нужна полная версия, чтобы настроить эту опцию.
Также обратите внимание, что код в вашем вопросе не готов к 64-битной версии, поскольку он приводит указатель к 4-байтовому целому числу.
Если вы используете новые версии Delphi (я тестировал с XE и XE2), лучший и самый простой способ - позвонить SetMinimumBlockAlignment(mba16Byte)
на первом месте в вашем коде.
Тогда позвоните регулярному GetMem
, New
или любая функция выделения памяти и убедитесь, что адрес выровнен по 16-байтовым границам
Редактировать:
Также, если вы предпочитаете использовать ручное исправление, лучший эффективный способ, который тратит меньше памяти, заключается в следующем:
var
lArraySz: LongInt;
lAdblRAp, lAdblRA: Pointer;
begin
// ...
GetMem(lAdblRAp,(lArraySz * SizeOf(Double)) + 16);
lAdblRA := Pointer((Integer(lAdblRAp) + 15) and $FFFFFFF0));
// ...
end;
Он будет использовать на 16 байт меньше для каждого выделения.