ПрограммированиеФорумОбщее

[C++] Быстрая проверка области памяти на предмет равенства значению. (3 стр)

Страницы: 1 2 3 4 Следующая »
#30
22:36, 8 янв 2011

Не.

      b |= mas[i + 0];
      b |= mas[i + 1]; 
      b |= mas[i + 2];
      b |= mas[i + 3];

Да.

      b0 |= mas[i + 0];
      b1 |= mas[i + 1]; 
      b2 |= mas[i + 2];
      b3 |= mas[i + 3];

Это может спасти, если у твоего процессора нет другого узкого места (например, чтения из памяти не каждый такт запускать может).

#31
22:46, 8 янв 2011

IronPeter, пробовал и так и так — результат идентичен - 200мс. Также пробовал включать поддержку SSE в опциях компилятора, что никак не повлияло.)

#32
0:16, 9 янв 2011

Если кому интересно, насчет memcmp который посоветовал Sbtrn. Devil.
с таким кодом:

bool onlyZeros = mas[0] == 0 && memcmp(mas, mas+1, SIZE * sizeof(int) - 4) == 0;

при тех же условиях (1Гб массив int, все нули кроме последнего), получаются такие результаты:

memcmp #0: 220 ms, onlyZeros : 0
memcmp #1: 220 ms, onlyZeros : 0
memcmp #2: 221 ms, onlyZeros : 0
memcmp #3: 225 ms, onlyZeros : 0
memcmp #4: 222 ms, onlyZeros : 0

*стоит отметить, что в целом функция показывает лучшие результаты, по сравнению с другими (кроме специфического случая как в примере).

#33
0:54, 9 янв 2011

наскока я знаю архитектуру то есть жестокий аппаратный вариант.
на каждую страницу памяти можно повесить прерывании на чтения на запись,....
так вот у нас уже посчитано для каждой странице нулевая она или нет. и есть счетчик сколько не нулевых страниц.
также на каждой странице висит прерывания на попытку записи.

как тока произошла попытка записи в страницу будет прерывании мы метим данную страницу как неопределенную, отключаемся от прерывания для данной странице, и уменьшаем счетчик ненулевых страниц.

когда нам нужно знать нулевая область или нет то смотрим счетчик ненулевых страниц и если он не 0 то область ненулевая,
в противном случаи пробегаемся по всем неопределенным страницам(до первой ненулевой) и корректируем счетчик ну далее если = 0 то область нулевая если != 0 то нет.


А вобще смысл обсуждать 1гб нулевых данных?
Часто приходиться пробегаться по коллекции и проверять на значение какой нибудь bool. но там данные не упорядочены, количество редко превышает 10к.
ДА еще на GUI можно.

#34
10:03, 9 янв 2011

rAmpArk
> IronPeter, пробовал и так и так — результат идентичен - 200мс. Также пробовал
> включать поддержку SSE в опциях компилятора, что никак не повлияло.)
компилятор MS? покажи асм-выхлоп того кода, что привел IronPeter, возможно компилятор не сделал оптимизацию под sse.

#35
10:52, 9 янв 2011

Я и не надеялся на SSE от компилятора. Я просто считаю такты процессора. Если частота 2 гигагерца и он умеет запускать чтение из памяти и арифметическую операцию каждый такт, то тогда тот цикл должен требовать 100 ms, т.е. вчистую шина должна ограничивать.

#36
13:12, 9 янв 2011

IronPeter
стало интересно. решил тоже посчитать.
вообщем компилятор выдает такой код:

   int i = 0;
00321021  xor         eax,eax  
00321023  jmp         main+30h (321030h)  
00321025  lea         esp,[esp]  
0032102C  lea         esp,[esp]  
    for(; i < size; i += 4) {
    b0 |= mas[i + 0];
00321030  or          ecx,dword ptr [ebp+eax*4-3E84h]  
    b1 |= mas[i + 1];
00321037  or          edx,dword ptr [ebp+eax*4-3E80h]  // эта пара инструкций спаривается
    b2 |= mas[i + 2];
0032103E  or          esi,dword ptr [ebp+eax*4-3E7Ch]  
    b3 |= mas[i + 3];
00321045  or          edi,dword ptr [ebp+eax*4-3E78h]  // и эта
0032104C  add         eax,4  
0032104F  cmp         eax,0FA0h  // здесь спаривания нету, т.к. чтение после записи
00321054  jb          main+30h (321030h)  
    }

итого, с учетом спаривания инструкций я насчитал 5 тактов в цикле (или чуть больше, т.к. я не помню, какая инструкция сколько занимает тактов). поправьте меня, если я не прав.
получается, что на вычисления затрачивается 2 такта, а на организация цикла 3? тогда можно попробовать вынести в цикл чуть больше вычислений. дискасс :)

#37
13:21, 9 янв 2011

RaZOR
видимо отдельно выделять 4 переменные не так уж необходимо:

    for(int i = 0; i < SIZE; i++) {
      b |= mas[i];
//000000013FCD11E0  mov         ecx,dword ptr [rdx-8]  
//000000013FCD11E3  add         rdx,10h  
//000000013FCD11E7  or          ecx,dword ptr [rdx-14h]  
//000000013FCD11EA  or          ecx,dword ptr [rdx-0Ch]  
//000000013FCD11ED  or          ecx,dword ptr [rdx-10h]  
//000000013FCD11F0  or          ebx,ecx  
//000000013FCD11F2  dec         r8  
//000000013FCD11F5  jne         main+1E0h (13FCD11E0h)  
    }

в итоге количество итераций получается SIZE/4

#38
13:30, 9 янв 2011

rAmpArk
итого,
у тебя: 6 тактов х size
у IronPeter: 5 тактов х (size/4)
вроде как...

edit: форматирование

#39
14:04, 9 янв 2011

RaZOR
> итого,
> у тебя: 6 тактов х size
> у IronPeter: 5 тактов х (size/4)
> вроде как...

да, из отличий - отсутствие мува, но все-таки (size/4) итераций, и время исполнения одинаково ~187мс, т.к., как я понял, одинаково число обращений к памяти.

    for(int i = 0; i < SIZE; i+=4) {
      b0 |= mas[i];
//000000013FDF1110  or          edi,dword ptr [rcx-8]  
      b1 |= mas[i+1];
//000000013FDF1113  or          esi,dword ptr [rcx-4]  
      b2 |= mas[i+2];
//000000013FDF1116  or          ebp,dword ptr [rcx]  
      b3 |= mas[i+3];
//000000013FDF1118  or          ebx,dword ptr [rcx+4]  
//000000013FDF111B  add         rcx,10h  
//000000013FDF111F  dec         rdx  
//000000013FDF1122  jne         main+110h (13FDF1110h)  
    }
#40
22:16, 9 янв 2011

susageP
к этому нет доступа из UserMode

#41
23:09, 9 янв 2011

RaZOR


а с __int64 что будет ?

небольшой анроллинг можно сделать однако

#42
6:08, 10 янв 2011

Pushkoff
> к этому нет доступа из UserMode
Вроде есть, называеться Protect у страниц

P.S. Смотри VirtualAlloc в MSDN и дальше по ссылкам

#43
11:51, 10 янв 2011

susageP
> на каждую страницу памяти можно повесить прерывании на чтения на запись,....
исключения

#44
19:45, 10 янв 2011

innuendo
> а с __int64 что будет ?
а он ему нужен? или что ты имеешь ввиду?

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.