Оптимизировать цикл

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Оптимизировать цикл

Сообщение Tin » 13.04.2006 (Чт) 9:29

Сабж...
Проблема в том, что массив PicBits ооооооооочень большой...

Код: Выделить всё
Do While Not Cnt >= UBound(PicBits)
       For I = 0 To 3
            PicBitsNew(Cnt2 + I) = PicBits(Cnt + I)
       Next
       Cnt2 = Cnt2 + 4
       Cnt = Cnt + ZM2
       BPLT = BPLT + 1
       If BPLT = C Then Cnt = Cnt + TpB: BPLT = 1
Loop
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 13.04.2006 (Чт) 9:43

Код: Выделить всё
Ub = UBound(PicBits)
Do While Not Cnt >= Ub
...

Это в глаза бросается..
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.04.2006 (Чт) 9:47

А почему Do...Loop, а не For...Next?
Lasciate ogni speranza, voi ch'entrate.

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 9:47

Вообще никак не ускоряет, ес честно - уже пробовал
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 13.04.2006 (Чт) 9:52

А может расписать задачу? Возможно тогда мысли появятся...
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.04.2006 (Чт) 9:55

Пусть не ускоряет, но смотреться будет красивее.
К тому же границы For...Next считаются только единожды, там вполне можно использовать UBound().
Lasciate ogni speranza, voi ch'entrate.

uhm
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1597
Зарегистрирован: 02.12.2004 (Чт) 15:21

Сообщение uhm » 13.04.2006 (Чт) 9:56

Что сразу вспомнилось - циклы от x до 0 работают немного быстрее, чем циклы от 0 до x. Вроде бы :?
Быть... или не быть. Вот. В чём вопрос?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.04.2006 (Чт) 9:59

Можно попробовать вместо битов работать с байтами. Должно помочь.
Lasciate ogni speranza, voi ch'entrate.

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 9:59

Что-то вроде... В Temp1 лежит БОЛЬШАЯ картинка, уменьшается на ZM и помещается Temp2
Код: Выделить всё
Sub PaintSmallPic2(Zm As Integer)
Temp2.Width = Temp1.Width / Zm
Temp2.Height = Temp1.Height / Zm

GetObject Temp1.Image, Len(PicInfo), PicInfo

BytesPerLine = (PicInfo.bmWidth * 3 + 3) And &HFFFFFFFC
ReDim PicBits(1 To BytesPerLine * PicInfo.bmHeight * 3) As Byte
ReDim PicBitsNew(1 To ((BytesPerLine * PicInfo.bmHeight * 3) / Zm ^ 2)) As Byte
Rem Загружаем картинку в массив
GetBitmapBits Temp1.Image, UBound(PicBits), PicBits(1)
Cnt2 = 1
Cnt = 1
Dim BPLT As Integer
BPLT = 1
Dim TpB As Integer
TpB = Temp1.Width + BytesPerLine
Dim C As Integer
C = Temp1.Width / 2
Dim I As Byte
Dim ZM2 As Byte
ZM2 = 4 * Zm
Dim UB As Double
UB = UBound(PicBits)
Dim TM As Long
TM = timeGetTime

Do While Not Cnt >= UB
       For I = 0 To 3
            PicBitsNew(Cnt2 + I) = PicBits(Cnt + I)
       Next
       Cnt2 = Cnt2 + 4
       Cnt = Cnt + ZM2
       BPLT = BPLT + 1
       If BPLT = C Then Cnt = Cnt + TpB: BPLT = 1
Loop
Me.Caption = timeGetTime - TM
'Set the bits back to the picture
SetBitmapBits Temp2.Image, UBound(PicBitsNew), PicBitsNew(1)

End Sub
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 10:02

Do...Loop потому что Cnt в цикле изменяется на TrB
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 13.04.2006 (Чт) 10:19

Tin писал(а):Что-то вроде... В Temp1 лежит БОЛЬШАЯ картинка, уменьшается на ZM и помещается Temp2


Что-то не пойму - почему бы просто не поместь картинку сразу в Temp2 (PictureBox?) нужного размера? Для этого никаких циклов не нужно...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 13.04.2006 (Чт) 10:24

Код: Выделить всё
Ub = UBound(PicBits)
Do While Cnt < Ub
Больше нечего ускорять.
Лучший способ понять что-то самому — объяснить это другому.

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 10:37

2Andrey Fedorov: Мне нужен этот массив в уменьшенном виде для последующих действий
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 13.04.2006 (Чт) 10:59

Tin писал(а):2Andrey Fedorov: Мне нужен этот массив в уменьшенном виде для последующих действий


Ну и бери его уже из новой картинки.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 11:04

Ну вообщем не то это... Мне нужно именно из большого массива сделать маленький - а это очень долго...
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.04.2006 (Чт) 11:15

Tin писал(а):Do...Loop потому что Cnt в цикле изменяется на TrB

Ну и что?
Кто мешает его менять в For...Next?
Lasciate ogni speranza, voi ch'entrate.

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 11:18

Все равно не особо помагло...
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 13.04.2006 (Чт) 12:02

А после этого скомпилируй с опцией Remove array bounds check.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Captain
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 04.02.2005 (Пт) 21:50
Откуда: Moskau

Re: Оптимизировать цикл

Сообщение Captain » 13.04.2006 (Чт) 12:50

Tin писал(а):
Код: Выделить всё
       For I = 0 To 3
            PicBitsNew(Cnt2 + I) = PicBits(Cnt + I)
       Next

а если так?

Код: Выделить всё
CopyMemory PicBitsNew(Cnt2), PicBits(Cnt), 4

Faust
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 649
Зарегистрирован: 29.12.2003 (Пн) 13:38
Откуда: лаборатория

Сообщение Faust » 13.04.2006 (Чт) 14:33

For I = 0 To 3

а четвертый канал используется?
Листинги не горят!

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 14:39

Вот что-то более новое и что нуждается в ХОРОШЕЙ оптимизации - врмея выполнение на картинке 2048х1536 около 16 секунд на 2000 целере.

Что этот кусок делает:
Уменьшает картинку в Temp1 в Zm раз и помещает её в Temp2. При этом уменьшеная картинка не приобретает квадратиков... Блурится вообщем

Код: Выделить всё
Sub PaintSmallPic3(Zm As Integer)
Dim TM As Long
Dim TM2 As Long
Dim TpB As Integer
Dim C As Integer
Dim I As Byte
Dim I1 As Integer
Dim UB As Double
Dim X As Integer
Dim Y As Integer
Dim MyBitmap() As MBitmap
Dim TempSum() As Integer
TM = timeGetTime
Temp2.Width = Temp1.Width / Zm
Temp2.Height = Temp1.Height / Zm
GetObject Temp1.Image, Len(PicInfo), PicInfo
BytesPerLine = (PicInfo.bmWidth * 3 + 3) And &HFFFFFFFC
ReDim PicBits(1 To BytesPerLine * PicInfo.bmHeight * 3) As Byte
ReDim PicBitsNew(1 To BytesPerLine * PicInfo.bmHeight * 3) As Byte
'ReDim MyBitmap(1 To Temp1.Width, 1 To Temp1.Height) As MBitmap
ReDim TempSum((Temp1.Width / Zm) * 3) As Integer
Rem Загружаем картинку в массив
GetBitmapBits Temp1.Image, UBound(PicBits), PicBits(1)
C = Temp1.Width
UB = UBound(PicBits)
TM2 = timeGetTime
AddLog "Время загрузки в массив: " & TM2 - TM

TM = timeGetTime
Dim WPic As Integer
Dim XStp As Integer
Dim YStp As Integer
Dim ZmSQR As Integer
Dim PBNCount As Double
PBNCount = 1
ZmSQR = (Zm ^ 2)
WPic = 1
X = 1
Y = 1
XStp = 1
YStp = 1
For Cnt = 1 To UB - 1 Step 4
    For I = 0 To 2
        TempSum(X + I) = TempSum(X + I) + PicBits(Cnt + I)
    Next
    XStp = XStp + 1
    If XStp > Zm Then XStp = 1: X = X + 3
    WPic = WPic + 1
    If WPic > C Then
        WPic = 1
        X = 1
        YStp = YStp + 1
        If YStp > Zm Then
            Rem Обработан некий участок массива, подготовка и запись его в новый массив
            YStp = 1
            For I1 = 1 To UBound(TempSum) Step 3
                For I = 0 To 2
                    TempSum(I1 + I) = TempSum(I1 + I) / ZmSQR
                    PicBitsNew(PBNCount) = TempSum(I1 + I)
                    TempSum(I1 + I) = 0
                    PBNCount = PBNCount + 1
                Next
                PicBitsNew(PBNCount) = 0
                PBNCount = PBNCount + 1
            Next
        End If
    End If
Next

TM2 = timeGetTime
SetBitmapBits Temp2.Image, UBound(PicBitsNew), PicBitsNew(1)
AddLog "Время зарузки в Temp2: " & TM2 - TM
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 13.04.2006 (Чт) 14:54

Компиляция в Native code может дать прирост где-то на порядок...
Попробуй.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Tin
Woodsman
Woodsman
Аватара пользователя
 
Сообщения: 1001
Зарегистрирован: 08.12.2001 (Сб) 11:00
Откуда: Kazakhstan

Сообщение Tin » 13.04.2006 (Чт) 15:01

После компиляции в Native код с галочкой Remove array bounds check скорость обработки стала около 2х секунд...
888888__88__88____88
__88________8888__88
__88____88__88__8888
__88____88__88____88


Вернуться в Visual Basic 1–6

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

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

    TopList