Первый раз такое!

Раздел посвящен программированию с использованием Power Basic.
pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Первый раз такое!

Сообщение pronto » 09.08.2007 (Чт) 8:38

Первый раз я столкнулся с тем, что аналогичный код в PB работает медленнее, чем в VB!

Код: Выделить всё

   b = 205
   For t = 1 To Iterations '9000000
      'For i = 0 To 7  ' 1 bpp -> 8 bpp (most fast)
      '   aByte(x * 8 + i, y) = Bit(b, i) '(b And ps(i)) \ ps(i)
      'Next
     
      aByte(x, y) = b And 15 ' 4 bpp -> 8 bpp
      aByte(x + 1, y) = (b And 240) \ 16   
   Next


в PB ~165 мс
в VB ~125 мс!

Пожалуйста, как заставить PB делать это быстрее?!
O, sancta simplicitas!

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 09.08.2007 (Чт) 10:12

Переменная b не вычисляется в цикле ...., x, y тоже нигде не фигурирует

aByte(x, y) = b And 15 --- ???
aByte(x + 1, y) = (b And 240) \ 16 --- ???

покажи полный код на VB и PB

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 09.08.2007 (Чт) 10:52

b - переменная типа Byte (она и не должна меняться в цикле t)
x и y значения не имеют.

Вся проблема в двух строчках
Код: Выделить всё
aByte(x, y) = b And 15 '
aByte(x + 1, y) = (b And 240) \ 16


в первой - извлекаются младшие 4 бита переменной b и кладутся в элемент байтового массива,
во второй - извлекаются старшие 4 бита из переменной b и кладутся в следующий элемент байтового массива...
O, sancta simplicitas!

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 09.08.2007 (Чт) 11:01

Код: Выделить всё
b = 205
b1 = b And 15
b2 = (b And 240) \ 16

For t = 1 To Iterations '9000000
      aByte(x, y) = b1
      aByte(x + 1, y) = b2
Next


Если b не меняется внутри цикла, то логичнее вычислить выражения до начала цикла. Просто на VB транслятор это делает автоматически, а PB всё время вычисляет выражение внутри цикла. Вот отсюда и отставание, плюс переменная типа byte медленно обрабатывается.

можешь добавить в начале вот эту строчку для ускорения цикла

Код: Выделить всё
REGISTER T as LONG

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 09.08.2007 (Чт) 11:24

логичнее вычислить выражения до начала цикла. Просто на VB транслятор это делает автоматически, а PB всё время вычисляет выражение внутри цикла


Действительно, переписал и успокоился :D

Код: Выделить всё
   For t = 1 To Val(Text1.Text) '9000000

      b = Int(Rnd * 255)
      aByte(x, y) = b And 15
      aByte(x + 1, y) = (b And 240) \ 16

   Next


VB ~1680 мс
PB ~820 мс!
Спасибо, теперь буду учитывать, что компилятор PB хуже оптимизирует код!

P.S. Это был тестовый код. Кстати, а можно ускорить ассемблером?
O, sancta simplicitas!

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 09.08.2007 (Чт) 12:33

что компилятор PB хуже оптимизирует код!


Не согласен. Все зависит от того как написан код.
ВБ оптимизирует выражения которые не вычисляются внутри цикла.
ПБ не делает это - т.к. невычисляемые выражения внутри циклов задача программиста.

а так ПБ очень хорошо оптимизирует код программы.
Кстати, а можно ускорить ассемблером?


1. Можно использовать указатели для доступа к массивам.
2. Использовать тип LONG для вычисления выражений в купе с АСМ
что то вроде:
Код: Выделить всё
 
  ! mov eax, b
  ! and eax, &H0015
  ' в EBX записать указатель на aByte(x, y)
  ! mov [ebx], eax

и т.д. для следующего выражения

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 10.08.2007 (Пт) 9:46

Указатель на массив использовать так?

Код: Выделить всё
local b as byte
bp = varptr(aByte(0)) ' указатель на первый элемент массива

for y& = 0 to H
  for x& = 0 to W
    b = @bp[x&, y&] ' получить значение из массива
  next
next
O, sancta simplicitas!

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 10.08.2007 (Пт) 13:34

Код: Выделить всё
LOCAL bp AS BYTE PTR
bp = VARPTR( abyte(0,0) )
FOR x = 0 TO H
FOR y = 0 TO W
        b = @bp[x OF H, y OF W]
NEXT
NEXT


или же организовать линейный доступ к массиву
Код: Выделить всё
LOCAL bp AS BYTE PTR
bp = VARPTR( abyte(0,0) )
FOR L = 0 TO H*W - 1
       b = @bp[ L ]
NEXT


почитай хелп файл: Data Types -> Pointer Data Types

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 10.08.2007 (Пт) 14:32

Еще раз огромное спасибо!
Первый вариант подходит идиально!
O, sancta simplicitas!


Вернуться в Power Basic

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

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

    TopList