Альтернатива ручному исправлению выравнивания данных 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 байт меньше для каждого выделения.

Другие вопросы по тегам