Выравнивание данных под работу с SSE

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Выравнивание данных под работу с SSE

Сообщение Aloner » 22.12.2008 23:56:38

Для повышения скорости программы пробую использовать SSE инструкции, но для эффективной работы с этими инструкциями необходимо выравнивать данные на границу 16 (для movaps в частности), иначе смысл этих инструкций в плане скорости теряется. Собственно вопрос: как нужно выравнивать данные в ФП на адрес кратный 16 (например адрес массива)?
Aloner
новенький
 
Сообщения: 13
Зарегистрирован: 08.12.2008 16:18:41

Re: Выравнивание данных под работу с SSE

Сообщение MageSlayer » 24.12.2008 15:37:49

Не вижу особой проблемы.

Выделять память с запасом в n-1 байт и размещать массив по адресу (указатель+n-1) and 16.
MageSlayer
постоялец
 
Сообщения: 216
Зарегистрирован: 07.09.2006 12:30:44

Re: Выравнивание данных под работу с SSE

Сообщение Aloner » 25.12.2008 00:18:56

Огромнеееееейшеееее спасибо!
Т.е. получается вот такая процедура для выделения блока памяти:

Procedure New16(Var P:Pointer;S:Longint);
Begin
GetMem(P,S+16);
S:=Longint(P);
P:=Pointer(S shr 4 shl 4+16);
End;

Как я сам не додумался :oops:
Ну а если на уровне компилятора выравнивать? а то в этом методе придется хранить начальный адрес и выравненный адрес для каждого блока, а этих блоков может быть достаточно много,и вариант обьединить все блоки в один блок тоже не подходит, так как количество блоков меняется динамически в большом диапозоне.
Aloner
новенький
 
Сообщения: 13
Зарегистрирован: 08.12.2008 16:18:41

Re: Выравнивание данных под работу с SSE

Сообщение bw » 25.12.2008 02:50:23

Стандартный менеджер кучи веделяет мозг с выравниванием до 8 байт. Хотя никто не может гарантировать, что это правило не изменится в следующих версиях FPC. Можно написать свой менеджер, опираясь на код существующего.
В случае с New16 ты гарантированно не сможешь освободить память FreeMem (смещение указателя происходит даже, если он находится уже на границе 16 байт). Так было бы лучше:
Код: Выделить всё
Ptr := GetMem(Size + 15);
if DWord(Ptr) and $F > 0 then
  Ptr := Pointer((DWord(Ptr) and $FFFFFFF0) + 16);

С учетом того что у тебя GetMem в 50% уже вернет "выравненный указатель" получается экономия в этих случаях по 32 байта.

Но лучше не выравнивать указатель при выделении памяти (так придется хранить где то еще один, оригинальный, что бы её можно было освободить), а просто выполнять размещение данных в выделенном буфере, с учетом выравнивания. Т.е. данные должны быть размещены со смещением от начала буфера от 0 до 15.

p.s. Походу я ошибся, стандартный менеджер (в версии FPC 2.2.0 под Linux) выполняет выравнивание не до 8 байт, а до 16 :-). Так что ничего больше делать не нужно.

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Выравнивание данных под работу с SSE

Сообщение Cheb » 26.12.2008 12:47:27

А с аллокатором для динамических массивов как получается? Ведь там первые 8 байт - служебная информация. Или он так аллоцирует, чтобы нолевой элемент массива начинался с границы в 16 байт?
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Выравнивание данных под работу с SSE

Сообщение bw » 26.12.2008 16:04:32

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

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Выравнивание данных под работу с SSE

Сообщение Aloner » 26.12.2008 22:04:29

bw
Прежде всего, спасибо за ответ :))
Про то, что придется хранить два указателя на блок и про идею с общим блок и одним смещением для него, я писал - не вариант, хотя если больше не будет других возможностей, заюзаю это способ.
А то что в ФП 2.2.0 под ГО32 тоже идет выравнивание на 16 байт как и под линуху я не уверен, так как если указатель не выравнивать, ассемблерная вставка с командой movaps гарантировано вызовет ошибку (#GP если я не ошибаюсь). Если же выравнивать - все работает без ошибок.
Еще раз спасибо за код, опробую и переведу на ассемблер, а то уж больно мне это переопределение типов не нравится :)
Aloner
новенький
 
Сообщения: 13
Зарегистрирован: 08.12.2008 16:18:41

Re: Выравнивание данных под работу с SSE

Сообщение Cheb » 27.12.2008 02:35:56

Врядли в выделяемой области есть служебная информация,

А именно так все массивы и устроены. Только сам массив в итоге - указатель не на сам выделенный блок, а на его 8-й байт. Таким образом, служебная информация оказывается по отрицательному смещению. Если попробуешь привести массив к указателю и освободить его... БУУУМ! :twisted:
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Выравнивание данных под работу с SSE

Сообщение bw » 27.12.2008 06:04:37

> А то что в ФП 2.2.0 под ГО32 тоже идет выравнивание на 16 байт как и под линуху я не уверен
А я уверен :-). Проверь, это не сложно:
Код: Выделить всё
begin
  WriteLn(HexStr(DWord(GetMem(1)), 8));
  WriteLn(HexStr(DWord(GetMem(1)), 8));
  WriteLn(HexStr(DWord(GetMem(1)), 8));
  WriteLn(HexStr(DWord(GetMem(1)), 8));
end.

На какой границе находятся выделенные блоки? 16?

> movaps гарантировано вызовет ошибку
Решай проблемы по мере их поступления :-). А вдруг никогда не возникнет такой ошибки, а ты уже несколько дней не можешь начать работу только из-за потенциальной возможности. Можешь, например использовать свои GetMem/FreeMem, вот самая простая реализация GetMem, которая не выполняет выравнивание, а только проверяет, что бы блоки были выравнены:
Код: Выделить всё
function MyGetMem(Size: DWord): Pointer;
begin
  Result := GetMem(Size);
  if DWord(Result) and $F > 0 then
  begin
    FreeMem(Result);
    raise Exception.Create('Жопа');
  end;
end;

Если этого окажется не достаточно, перепишешь MyGetMem и MyFreeMem так, что бы они гарантировали выравнивание.

> БУУУМ!
>> Я не изучал код стандартного менеджера кучи.

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Выравнивание данных под работу с SSE

Сообщение Aloner » 28.12.2008 01:28:53

bw
)) Проверил я твоим кодом(хотя до этого также и своим проверял, иначе тему вообще бы не создавал),результаты:
0010D9E8 (1104360 / 16 = 69022,5)
0010D9F8 (1104376 / 16 = 69023,5) и т.д.
" А вдруг никогда не возникнет такой ошибки" - я проверял след. кодом, и сразу же получил ошибку(что естественно так как данные не выравнены на 16):

Код: Выделить всё
Type
PVector= ^TVector;
TVector=Record X,Y,Z,W:Single;End;

Var V:PVector;
Begin
New(V);
Asm
Mov eax,V
Movaps xmm0,[eax]
End;
Dispose(V);
End.


Может у тебя директива включена какая нить для выравнивания? И еще: Я работаю под Дос(расширитель GO32).
P/S. Exception "жопа" прикальнула %)
Последний раз редактировалось Aloner 28.12.2008 01:40:12, всего редактировалось 1 раз.
Aloner
новенький
 
Сообщения: 13
Зарегистрирован: 08.12.2008 16:18:41

Re: Выравнивание данных под работу с SSE

Сообщение Mr.Smart » 28.12.2008 01:35:26

Есть директива {$ALIGN
в документации написано следующее:
The {$ALIGN directive can be used to select the data alignment strategy of the compiler for the Mac
OS. Only valid in MACPAS mode, it can have the following values:


... Почему бы не расширить данную директиву на другие платформы?
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Выравнивание данных под работу с SSE

Сообщение Aloner » 28.12.2008 01:44:42

Mr.Smart
+1
Присоединяюсь к просьбе!
Я еще бы лучше ввести оператор, который бы указывал что например именно этот массив или этот указатель нужно выравнять на указанную границу...
Aloner
новенький
 
Сообщения: 13
Зарегистрирован: 08.12.2008 16:18:41

Re: Выравнивание данных под работу с SSE

Сообщение Sergei I. Gorelkin » 28.12.2008 10:51:41

Я очень далек от этой темы, но вообще-то компилятор умеет генерить SSE код, а стало быть, и самостоятельно выравнивать все что нужно. Для этого, наверное, нужно разрешить ему этот код генерить (опция -Cfsse2), и объявлять типы переменных наподобие Tvector = array[0..3] of single (хотя, может он настолько умный, что и record x,y,z,w: single end; поймет).
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru