Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.10.2010, 09:35   #1
Я_и
Пользователь
 
Регистрация: 14.09.2010
Сообщений: 37
По умолчанию Можно ли применить FillChar для динамического массива

Подскажите, пожалуйста, как быстро заполнить одномерный динамический массив? Ну очень быстро=)
Я_и вне форума Ответить с цитированием
Старый 02.10.2010, 10:21   #2
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Код:
var
  A: packed array of TSomething;
...
  FillChar(A[0], SizeOf(A[0]) * Length(A), 0);
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 02.10.2010, 10:52   #3
ViktorXP
Форумчанин
 
Аватар для ViktorXP
 
Регистрация: 24.11.2006
Сообщений: 108
По умолчанию

Заполнить чем?
если массив только выделяется то он уже чистый (делфя сама об этом заботится).
ViktorXP вне форума Ответить с цитированием
Старый 03.10.2010, 13:21   #4
Я_и
Пользователь
 
Регистрация: 14.09.2010
Сообщений: 37
По умолчанию

Массив как раз требуется очищать каждые 0.05с. Т.к. он является буффером глубины прорисовки кадра....
Я_и вне форума Ответить с цитированием
Старый 03.10.2010, 15:19   #5
Tronix
Форумчанин
 
Аватар для Tronix
 
Регистрация: 15.06.2010
Сообщений: 740
По умолчанию

Если размер массив четный и делится на 4, можно прямо ассемблерной вставкой:

Код:
asm
   mov edi, Massiv  // Massiv - должен быть типа Pointer.
   mov ecx, размер массива деленный на 4
   xor eax,eax // заполняем нулями
   rep stosd
end;
Еще можно через mmx кидать сразу по 8 байт, а через sse вообще по 16 байт за раз, но могут быть косяки во-первых из-за выравнивания массива в памяти, а во-вторых из-за большой латентности самих SIMD комманд. Так что тут палка о двух концах...

Вот, померил кстати, да, асмовая вставка оказалась самым быстрым вариантом. MMX и SSE только тормозят, не знаю почему так. Может конечно я косо написал...
Код:
{$ALIGN 8}
Uses Windows;
Const
      ArrSize  = 134217728;   //128Mb for test array
      Cnt      = 50;          //tests count
Var
      Timer             : Cardinal;
      PriorityClass,
      Priority          : Cardinal;
      Mas               : Pointer;
      i                 : Cardinal;

Begin
      GetMem(Mas,ArrSize); // Get 128Mb for array

      PriorityClass := GetPriorityClass(GetCurrentProcess);
      Priority := GetThreadPriority(GetCurrentThread);
      SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);

      Timer := GetTickCount;
      For i := 1 to Cnt do
        FillChar(Mas^,ArrSize,0);

      WriteLn('FillChar() time: ',GetTickCount-Timer,' ms');

      Timer := GetTickCount;
      For i := 1 to Cnt do
      asm
            mov edi,Mas
            mov ecx,ArrSize/4
            xor eax,eax
            rep stosd
      end;

      WriteLn('rep stosd time: ',GetTickCount-Timer,' ms');

      Timer := GetTickCount;
      For i := 1 to Cnt do
      asm
            mov edi,Mas
            pxor mm0,mm0
            mov ecx,ArrSize/8
         @fill:
            movq [edi],mm0
            add edi,8
            loop @fill
            emms
      end;

      WriteLn('MMX fill: ',GetTickCount-Timer,' ms');

      Timer := GetTickCount;
      For i := 1 to Cnt do
      asm
            mov edi,Mas
            xorps xmm0,xmm0
            mov ecx,ArrSize/16
         @fill:
            movss [edi],xmm0
            add edi,16
            loop @fill
            emms
      end;

      WriteLn('SSE fill: ',GetTickCount-Timer,' ms');

      SetThreadPriority(GetCurrentThread, Priority);
      SetPriorityClass(GetCurrentProcess, PriorityClass);

      Write('all tests done. press ENTER to exit');
      ReadLn;
      FreeMem(Mas);
End.
Результаты работы:
Цитата:
FillChar() time: 5890 ms
rep stosd time: 5875 ms
MMX fill: 6141 ms
SSE fill: 5906 ms
Можете потестить на своем процессоре, прикладываю уже скомпиленый файл и исходник. Если что, собирать FPC v2.4.0 с ключем -Mtp.
Чтобы понять рекурсию, сперва нужно понять рекурсию.

Последний раз редактировалось Tronix; 03.10.2010 в 19:46.
Tronix вне форума Ответить с цитированием
Старый 03.10.2010, 16:33   #6
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Хоть бы версию Delphi указали.

FillChar в D7 и D2007 - как небо и земля.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 03.10.2010, 16:40   #7
Tronix
Форумчанин
 
Аватар для Tronix
 
Регистрация: 15.06.2010
Сообщений: 740
По умолчанию

Я специально дал сорцы - берите да проверяйте для какой надо делфи. Хоть для Delphi v7, хоть для Delphi 2010. Результаты выше были для Free Pascal Compiler v2.4.0 конкретно.

Ща на Delphi v7 проверю. Да те же самые резалты тащемта:
Цитата:
FillChar() time: 5860 ms
rep stosd time: 5812 ms
MMX fill: 6094 ms
SSE fill: 5859 ms
UPD: Так, заменил MOVSS на MOVNTDQ в цикле с SSE и результат получился для SSE - 2688 ms.
Чтобы понять рекурсию, сперва нужно понять рекурсию.

Последний раз редактировалось Tronix; 03.10.2010 в 17:16.
Tronix вне форума Ответить с цитированием
Старый 03.10.2010, 18:27   #8
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

Цитата:
требуется очищать каждые 0.05с. Т.к. он является буффером глубины прорисовки кадра....
м... Что именно имеется ввиду под "буффером глубины"?
А при этой прорисовке нельзя просто менять значения на новые? А то лишние "очистки" - зло...

По моим сведеньям быстрее всего на MMX... Источник вроде был достаточно надёжный, хотя сам не проверял...

Tronix, за тест спасибо, ща тоже померяю... Только жалко FPC у мня не фурычит, сделаю на Делфи...
А почему через GetTickCount, а не через QueryPerformanceCounter?
Да и по-хорошему проверять нужно не по TIME_CRITICAL, а вообще по всем...


P.S.
Tests: 1641, 1593, 2282, 2250;
I am the First of Cyber Evolution...
I am the First to Program your Future...

Последний раз редактировалось DomiNick; 03.10.2010 в 18:32. Причина: P.S.
DomiNick вне форума Ответить с цитированием
Старый 03.10.2010, 18:43   #9
Tronix
Форумчанин
 
Аватар для Tronix
 
Регистрация: 15.06.2010
Сообщений: 740
По умолчанию

Цитата:
Сообщение от DomiNick Посмотреть сообщение
Tronix, за тест спасибо, ща тоже померяю... Только жалко FPC у мня не фурычит, сделаю на Делфи...
А почему через GetTickCount, а не через QueryPerformanceCounter?
Да и по-хорошему проверять нужно не по TIME_CRITICAL, а вообще по всем...
Что значит не по TIME_CRITICAL? Я делаю самый высокий приоритет для основного потока, чтобы цикл теста винда и другие проги не особо дергали. Почему через GetTickCount? Да хз на самом деле, первое что вспомнил просто )) можно как угодно замерять, хоть через rdtsc. И еще раз повторюсь, если в цикле теста SSE заменить команду MOVSS на команду MOVNTDQ, то скорость повышается в 2 (!!!) раза.
Код:
      Timer := GetTickCount;
      For i := 1 to Cnt do
      asm
            mov edi,Mas
            xorps xmm0,xmm0
            mov ecx,ArrSize/16
         @fill:
            movntdq [edi],xmm0
            add edi,16
            loop @fill
            emms
      end;

      WriteLn('SSE fill: ',GetTickCount-Timer,' ms');
Еще не плохо бы выравнивать как-то по 16-байтной границы, но я честно говоря не очень с этим разобрался. Там какие-то prefetch и тд, не понимаю я их. Может тот, кто в SSE хорошо шарит подскажет.
Чтобы понять рекурсию, сперва нужно понять рекурсию.
Tronix вне форума Ответить с цитированием
Старый 03.10.2010, 19:00   #10
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

Цитата:
Что значит не по TIME_CRITICAL?
Многие считают что мерить надо именно при нормальном приоритете, чтоб винда и другие проги как раз таки-мешались... Более полевые условия чтоль...

Какой компилятор у вас? *
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
создать клас для динамического массива supra89kren Общие вопросы C/C++ 5 30.03.2010 00:23
Можно ли к функции ellipse(x1,y1,x2,y2) применить прозрачный Brush Mr.Steroid Мультимедиа в Delphi 2 04.03.2010 21:47
Переделать для динамического массива. Ueshua Общие вопросы C/C++ 1 20.12.2009 21:33
операция NEW для динамического массива -ushёl- Общие вопросы C/C++ 0 14.11.2009 22:00
Как можно применить к тексту комонент PageSetupDialog Bill Gates Общие вопросы Delphi 1 30.12.2007 20:17