Тест скорости
От: icWasya  
Дата: 27.12.04 13:03
Оценка:
какая процедура proc1 или proc2 выполняется быстрее и почему
char M[4000*4100];
int proc1()
{
  int i,j,c;
  c=0;
  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4096 + j];
  return c;
}
int proc2()
{
  int i,j,c;
  c=0;
  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4097 + j];
  return c;
}
Re: Тест скорости
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.04 13:07
Оценка:
Здравствуйте, icWasya, Вы писали:

proc1 наверное, ведь умножение на 4096 заменится на сдвиг на 12 бит.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Тест скорости
От: BlackHeretic Израиль  
Дата: 27.12.04 13:07
Оценка:
Здравствуйте, icWasya, Вы писали:


W>какая процедура proc1 или proc2 выполняется быстрее и почему

W>
W>char M[4000*4100];
W>int proc1()
W>{
W>  int i,j,c;
W>  c=0;
W>  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4096 + j];
W>  return c;
W>}
W>int proc2()
W>{
W>  int i,j,c;
W>  c=0;
W>  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4097 + j];
W>  return c;
W>}
W>


Ясен красен proc1 — умножение заменится на сдвиг. Хотя опять же зависит от железа — современное железо шустро.
ICQ 156156278
Re: Тест скорости
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.04 13:09
Оценка: 1 (1)
Здравствуйте, icWasya, Вы писали:

proc1 наверное, ведь умножение на 4096 заменится на сдвиг на 12 бит.

Хотя после оптимизации обе будут выполняться одинаково. Оптимизированные версии выглядят так


char M[4000*4100];
int proc1()
{
  int i,j,c;
  c=0;
  for (j=0;j<4000;j++)for(i=0;i<16384000;i+=4096) c=c+M[i + j];
  return c;
}
int proc2()
{
  int i,j,c;
  c=0;
  for (j=0;j<4000;j++)for(i=0;i<16388000;i+=4097) c=c+M[i + j];
  return c;
}
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Тест скорости
От: Jax Россия  
Дата: 27.12.04 13:09
Оценка:
Видимо первая. Могу предположить что умножение на 4096 быстрее, чем на 4097, т.к. что бы умножить на 4096 достаточно сдвинуть биты влево на 12 позиций (2^12 = 4096).
Re: Тест скорости
От: korzhik Россия  
Дата: 27.12.04 13:10
Оценка:
Здравствуйте, icWasya, Вы писали:


W>какая процедура proc1 или proc2 выполняется быстрее и почему


proc2 быстрее
Re: Тест скорости
От: Кодт Россия  
Дата: 27.12.04 13:23
Оценка:
Здравствуйте, icWasya, Вы писали:


W>какая процедура proc1 или proc2 выполняется быстрее и почему


От оптимизации зависит. В принципе, обе можно свести к следующему:
inline void sumj(int& eax, int*& esi)
{
  for(int ecx=4000; ecx; --ecx) eax += *(esi++); // 1 инструкция MMX
}
int proc1()
{
  int eax = 0;
  int* esi = M;
  for(int edx=4000; edx; --edx)
    sumj(eax, esi),
    esi += 96;
  return eax;
}
int proc2()
{
  int eax = 0;
  int* esi = M;
  for(int edx=4000; edx; --edx)
    sumj(eax, esi),
    arr += 97;
  return eax;
}
Перекуём баги на фичи!
Re[2]: Тест скорости
От: korzhik Россия  
Дата: 27.12.04 13:34
Оценка:
Здравствуйте, korzhik, Вы писали:

W>>какая процедура proc1 или proc2 выполняется быстрее и почему


K>proc2 быстрее


кстати, я не пошутил
у меня на компе proc2 выполняется в 1.5 раза быстрее чем proc1.
Как такое может быть и почему???!!!
Протестируйте пожалуйста у себя:
#include <boost/progress.hpp>

char M[4000*4100];

int proc1()
{
    boost::progress_timer t;

    int c = 0;
    
    for (int j = 0; j < 4000; ++j)
        for (int i = 0; i < 4000; ++i) 
            c = c + M[i*4096 + j];
  
    return c;
}

int proc2()
{    
    boost::progress_timer t;
    int c = 0;

    for (int j = 0; j < 4000; ++j)
        for (int i = 0; i < 4000; ++i) 
            c = c + M[i*4097 + j];
  
    return c;
}

int main()
{
    proc1();
    proc2();
}
Re[3]: Тест скорости
От: Кодт Россия  
Дата: 27.12.04 14:07
Оценка:
Здравствуйте, korzhik, Вы писали:

K>кстати, я не пошутил

K>у меня на компе proc2 выполняется в 1.5 раза быстрее чем proc1.

Более того, тормоза возникают и на других числах, кратных 512...
(компилятор VC6 sp5, опции -GR -GX -Od|-Ox, компьютер Athlon 1400, 512К ОЗУ).
Перекуём баги на фичи!
Re[4]: Тест скорости
От: Кодт Россия  
Дата: 27.12.04 14:08
Оценка:
К>Более того, тормоза возникают и на других числах, кратных 512...
К>(компилятор VC6 sp5, опции -GR -GX -Od|-Ox, компьютер Athlon 1400, 512К ОЗУ).

Разумеется, использовал для перебора параметров не циклы, а шаблоны (чтобы в цикл ничего лишнего не попадало).
Перекуём баги на фичи!
Re[4]: Тест скорости
От: korzhik Россия  
Дата: 27.12.04 14:20
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Более того, тормоза возникают и на других числах, кратных 512...


То есть в этих случаях получается что сдвиг медленее чем умножение
И как вы можете это объяснить?
Re[5]: Тест скорости
От: icWasya  
Дата: 27.12.04 15:48
Оценка:
Здравствуйте, Вы писали:
>>proc2 выполняется в 1.5 раза быстрее чем proc1
>>Более того, тормоза возникают и на других числах, кратных 512...

а тормоза происходят не на умножении , а собственно на выборке из массива!
Re[6]: Тест скорости
От: Димариус Россия  
Дата: 27.12.04 20:43
Оценка:
Здравствуйте, icWasya, Вы писали:

W>Здравствуйте, Вы писали:

>>>proc2 выполняется в 1.5 раза быстрее чем proc1
>>>Более того, тормоза возникают и на других числах, кратных 512...

W>а тормоза происходят не на умножении , а собственно на выборке из массива!


У меня недавно тоже такая проблема возникла. Я множил матрицы. Матрицы 1024х1024 прога множила 90 секунд, а у моего друга — 20. Было обидно. Я использовал линейный массив и вручную вычислял индексы, а он массив массивов. Оказалось, что дело было как раз в загадочном числе 1024 (кратно 512). На других числах я даже, кажется, его рулил.
unsigned int n;        //1024
type *A, *B, *C;
type **Ai, **Bi, **Ci;

void mult(int stroke) {
    for (unsigned __int32 i = 0; i < n; i++) {
        for (unsigned __int32 j = 0; j < n; j++) 
            Ci[stroke][i] += Ai[stroke][j] * Bi[j][i];
//            C[stroke * n + i] += A[stroke * n + j] * B[j * n + i];
    }
}
Re[4]: Тест скорости
От: adontz Грузия http://adontz.wordpress.com/
Дата: 27.12.04 22:43
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Более того, тормоза возникают и на других числах, кратных 512...


Что-то я не понимаю почему так
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[5]: Тест скорости
От: Аноним  
Дата: 27.12.04 23:42
Оценка: 20 (2)
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, Кодт, Вы писали:


К>>Более того, тормоза возникают и на других числах, кратных 512...


A>Что-то я не понимаю почему так

Все очень просто
Число 4096 — магическое в архитектуре PC (пентиум и выше), т.к весит 12 бит. а память в кэше первого уровня имеет 12 битную адресацию, т.е 2 блока памяти находящиеся по адресу, имеющему одинаковый остаток от деления на 4096 будут иметь один адрес,(но с этим адресом аасоциируется не одна а несколько линий) и несмотря на то что имеется несколько линий для одного адреса, по коду видно, что 4000 раз подняд идет работа с одним адресом . После 4-5 циклов все линии заполнятся, и при следующем чтении, ПРОЦЕССОРУ необходимо будет прочитать всю линию в 16 байт для продолжения работы(он по другому не умеет). далее идет ещё более труба, но она в обоих кусках кода. Как некаторые не знают, число 4096 — магическое. Именно по этому адресу выравниваются данные во кэше второго уровня. И обмен с памятью происходит именно по страницам. следовательно, мы не скоро, а очень скоро придем к тому, что у нас кончится кэш и второго уровня, но к данному случаю это не относися.
З.Ы. этот код пример как НЕ НАДО ПИСАТЬ ПРОГРАММЫ
Re: Тест скорости
От: Аноним  
Дата: 28.12.04 13:53
Оценка:
Здравствуйте, icWasya, Вы писали:


W>какая процедура proc1 или proc2 выполняется быстрее и почему

W>
W>char M[4000*4100];
W>int proc1()
W>{
W>  int i,j,c;
W>  c=0;
W>  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4096 + j];
W>  return c;
W>}
W>int proc2()
W>{
W>  int i,j,c;
W>  c=0;
W>  for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4097 + j];
W>  return c;
W>}
W>



Вроде первая. По-моему больше попаданий в кеш
Re[6]: Тест скорости
От: PinkPanther  
Дата: 27.01.05 19:16
Оценка: 10 (1)
Здравствуйте, Аноним, Вы писали:

А>Все очень просто

А>Число 4096 — магическое в архитектуре PC (пентиум и выше)
А>З.Ы. этот код пример как НЕ НАДО ПИСАТЬ ПРОГРАММЫ
Так ведь выходит, что наоборот, надо писать именно как пр.2, ибо второй вариант работает у меня примерно вдвое скорее.
Я смотрел что там компилятор скомпилировал — так там он в обоих случаях поставил сложение, только
в первом случае с 4096, а во втором — 4097...

; 1275 : for (j=0;j<4000;j++)for(i=0;i<4000;i++) c=c+M[i*4096 + j];
xor esi, esi
$L58372:
lea ecx, DWORD PTR ?M@@3PADA[esi]
mov edx, 4000 ; 00000fa0H
$L58375:
movsx edi, BYTE PTR [ecx]
add eax, edi
add ecx, 4096 ; 00001000H
dec edx
jne SHORT $L58375
inc esi
cmp esi, 4000 ; 00000fa0H
jl SHORT $L58372
Re[3]: Тест скорости
От: okostya  
Дата: 28.01.05 07:59
Оценка:
Здравствуйте, korzhik, Вы писали:

K>у меня на компе proc2 выполняется в 1.5 раза быстрее чем proc1.


Тестил под шарпом:
Celeron 2.4
proc1 = 00:00:01.4999904
proc2 = 00:00:01.5468651
P4 2.4
proc1 = 00:00:01.2812336
proc2 = 00:00:00.6093672
Re: Тест скорости
От: icWasya  
Дата: 28.01.05 11:28
Оценка:
Ну что быстрее выполняется вроде бы выяснили.
А главный вопрос — почему proc2 быстрее proc1
Re: Тест скорости
От: Plague Россия  
Дата: 28.01.05 13:22
Оценка:
А что будет если порядок вызова функций поменять местами? возможно это кэш?
т.е.

не proc1();proc2();

а proc2();proc1();
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.