Глюки VB: Массивы

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Глюки VB: Массивы

Сообщение Aquarius » 16.07.2003 (Ср) 12:24

Так как одно их моих увлечений в программировании - оптимизация кода, то я постоянно что-то измеряю, сверяю и т.д. Но одну вешь я так и не смог понять, может здесь есть люди которые смогут объяснить. Вот код модуля:

Код: Выделить всё
Public Declare Function GetTickCount Lib "kernel32" () As Long

Sub Main()
    Dim t As Long
    Dim i As Long, j As Long, k As Long
    Dim A(1023, 767) As Long
   
    t = GetTickCount
   
    For k = 0 To 10
        For i = 0 To 1023
            For j = 0 To 767
                A(i, j) = 255
            Next
        Next
    Next
   
    MsgBox (GetTickCount - t) / 1000
End Sub

Код чисто условный, но ему можно придать некоторый смысл. к примеру массив в данном случае может представлять битмап размером с рабочий стол, а цикл производит заливку этого битмапа 11 раз красным цветом. Вот результаты на моем Pentium III 533/WinXP - 2,5 сек.

А вот этот же код но размеры массива несколько изменены:

Код: Выделить всё
Public Declare Function GetTickCount Lib "kernel32" () As Long

Sub Main()
    Dim t As Long
    Dim i As Long, j As Long, k As Long
    Dim A(1024, 768) As Long 'границы массива изменены
   
    t = GetTickCount
   
    For k = 0 To 10
        For i = 0 To 1023
            For j = 0 To 767
                A(i, j) = 255
            Next
        Next
    Next
   
    MsgBox (GetTickCount - t) / 1000
End Sub

Результат 0,34 сек.

Почему это происходит я не смог понять. Либо мой бейсик гонит либо бейсик вообще гонит. Прошу проверить на ваших системах.

Тесты проводились на программе скомпилированной с установкой флага Optimize fir fast code и включением всех флагов нетривиальной оптимизации.

В чем загвоздка, объясните!!!
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 16.07.2003 (Ср) 12:50

768 делится на 2^8 => считать надо не 10 разрядов, а два(он судя по всему 768 умножает на 1,2,3...)

Sebas
Неуловимый Джо
Неуловимый Джо
Аватара пользователя
 
Сообщения: 3626
Зарегистрирован: 12.02.2002 (Вт) 17:25
Откуда: столько наглости такие вопросы задавать

Сообщение Sebas » 16.07.2003 (Ср) 13:24

Такие веши надо тестить в VB FOR DOS - то бишь в однозадачных системах..
- Я никогда не понимал, почему они приходят ко мне чтобы умирать?

sebas<-@->mail.ru

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 16.07.2003 (Ср) 13:37

Я слышал про нечто подобное. Правда, это относилось с Access: если объявлять строковые поля длиной кратной 32 (или 16??? непомню), то время доступа и обработки существенно уменьшается. Проверить всё никак не удавалось, но теперь, после этого примера, верю.

Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Сообщение Aquarius » 16.07.2003 (Ср) 13:53

GoGosha писал(а):768 делится на 2^8 => считать надо не 10 разрядов, а два(он судя по всему 768 умножает на 1,2,3...)


Непонял, объясни...

Такие веши надо тестить в VB FOR DOS - то бишь в однозадачных системах..


Тестировал много раз. Результаты одни и те же.

Я слышал про нечто подобное. Правда, это относилось с Access: если объявлять строковые поля длиной кратной 32 (или 16??? непомню), то время доступа и обработки существенно уменьшается. Проверить всё никак не удавалось, но теперь, после этого примера, верю.


Дело не в размере полей или переменных, у меня в обоих вариантах массив объявлен с типом Long.
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

RayShade
Scarmarked
Scarmarked
Аватара пользователя
 
Сообщения: 5511
Зарегистрирован: 02.12.2002 (Пн) 17:11
Откуда: Russia, Saint-Petersburg

Сообщение RayShade » 16.07.2003 (Ср) 13:59

А ведь было же такое понятие как выравнивание структур по границе памяти. Но все его забыли. А зря, между прочим.

Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Сообщение Aquarius » 16.07.2003 (Ср) 14:41

А ведь было же такое понятие как выравнивание структур по границе памяти. Но все его забыли. А зря, между прочим.

О каком выравнивании ты говоришь?

Вопервых у меня массив элементов Long. А Long это сколько байт? Правильно 4. То есть хочешь не хочешь массив выровнен как надо.
И даже если бы это было не так. То в любом случае в первом вариант у меня идет следующее объявление:

Код: Выделить всё
Dim A(1023,767) as Long


Так как нумерация элементов начинается с 0 то в массиве всего

1024*768 = 786432 элемента. (все отлично выравнено)

Во втором случае
Код: Выделить всё
Dim A(1024,768) as Long
или
1025*769 = 788225 элемента. (нечетное число)

Так получется выравнивание элементов снижает скорость бейсика. Это что-то новое???[/quote]
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

FaKk2
El rebelde gur&#250;
El rebelde gur&#250;
Аватара пользователя
 
Сообщения: 2031
Зарегистрирован: 09.03.2003 (Вс) 22:10
Откуда: Los Angeles

Сообщение FaKk2 » 16.07.2003 (Ср) 17:24

Первый пример: 2,043 секунды
Второй пример: 2,013 секунды
Комп: 800\256
Разница небольшая, но есть.
Но не такая катасрофическая :wink:
Что то ты напутал, ИМХО :wink:
Для получения ответа надо продемонстрировать качества, позволяющие стать компетентным — внимательность, вдумчивость, наблюдательность, желание активно участвовать в выработке решения.

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 16.07.2003 (Ср) 17:31

А ты откомпилировал?

FaKk2
El rebelde gur&#250;
El rebelde gur&#250;
Аватара пользователя
 
Сообщения: 2031
Зарегистрирован: 09.03.2003 (Вс) 22:10
Откуда: Los Angeles

Сообщение FaKk2 » 16.07.2003 (Ср) 17:43

skiperski писал(а):А ты откомпилировал?

Нет.
Сейчас выставил флажки Favor Pentium Pro
Запустил в IDE первый показал: 1,873
второй:1,933

Скомпилил:
Первый: 1,412
Второй: 0,21

Выставил все флажки в Advanced Compile и скомпилировал
Первый: 1.352
Второй: 0,8

Точно...разница есть.....вот загадка :roll:
Для получения ответа надо продемонстрировать качества, позволяющие стать компетентным — внимательность, вдумчивость, наблюдательность, желание активно участвовать в выработке решения.

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 16.07.2003 (Ср) 17:59

Какая загадка? Всё очень просто!
768=1100000000 в двоичной системе, а
767=1011111111 мы умножаем это на 1,10,11,100,101 и. т. д.
при этом чтоб умножить 1100000000 на какое либо число надо только первые два разряда умножить(незнаю алгоритмов машинного умножения может нули умножаются быстрее единиц)

Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Сообщение Aquarius » 17.07.2003 (Чт) 7:39

GoGosha писал(а):Какая загадка? Всё очень просто!
768=1100000000 в двоичной системе, а
767=1011111111 мы умножаем это на 1,10,11,100,101 и. т. д.
при этом чтоб умножить 1100000000 на какое либо число надо только первые два разряда умножить(незнаю алгоритмов машинного умножения может нули умножаются быстрее единиц)


Заранее отвечаю процессор производит соответсвующие операции над каждым битом, без его проверки.

Сам подумай что будет быстрее работать:
1. Проверить бит на 0
2. Ноль - перейти к следующему биту, goto 1
3. Не ноль - выполнить нек. опцию, перейти к следующему биту, goto 1

Или:
2. выполнить нек. опцию, перейти к следующему биту, goto 1

Странно, что более опытные модераторы воздерживаются от высказываний.
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

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

Сообщение GSerg » 17.07.2003 (Чт) 8:12

Я, конечно, не более опытный, и даже не модер :)
Но, проведя всего 1 (один) ченьдж кода, я нашёл причину :)

Ты перебирешь массив сначала по строкам, а затем по столбцам. Работая в VB, нужно поступать наоборот - перебирать сначала столбцы, а затем строки. Вот что получилось у меня.
  • Код 1, оригинальный - 1.056 сек
  • Код 2, оригинальный - 0.175 сек

  • Код 1, Столбцы :arrow: Строки - 0.064 сек
  • Код 2, Столбцы :arrow: Строки - 0.064 сек


Так что всё дело в расчёте координат очередного элемента массива в памяти.


ЗЫ: ИМХО.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 17.07.2003 (Чт) 10:20

Aquarius писал(а):
GoGosha писал(а):Какая загадка? Всё очень просто!
768=1100000000 в двоичной системе, а
767=1011111111 мы умножаем это на 1,10,11,100,101 и. т. д.
при этом чтоб умножить 1100000000 на какое либо число надо только первые два разряда умножить(незнаю алгоритмов машинного умножения может нули умножаются быстрее единиц)


Заранее отвечаю процессор производит соответсвующие операции над каждым битом, без его проверки.

Сам подумай что будет быстрее работать:
1. Проверить бит на 0
2. Ноль - перейти к следующему биту, goto 1
3. Не ноль - выполнить нек. опцию, перейти к следующему биту, goto 1

Или:
2. выполнить нек. опцию, перейти к следующему биту, goto 1

Странно, что более опытные модераторы воздерживаются от высказываний.


если процессор умножал бы "в столбик"(что очень мало вероятно скорее всего используется алгоритм Шёнхаге-Штрассена) то лишние нули во много сократили бы процесс. Но могут использоватся и похожие алгоритмы

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 17.07.2003 (Чт) 10:22

http://www.i2.com.ua/index.php?dir=Arti ... er.htm&f=3

сверх-быстрое умножение
если кому интересно

Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Сообщение Aquarius » 19.07.2003 (Сб) 6:18

если процессор умножал бы "в столбик"(что очень мало вероятно скорее всего используется алгоритм Шёнхаге-Штрассена) то лишние нули во много сократили бы процесс. Но могут использоватся и похожие алгоритмы

Чтобы узнать что некоторый бит равен нулю, его для начала нужно проверить на ноль. А это уже лишние операции.


GSerg ща проверю. Хотя логики в том чтобы обрабатывать массивы по столбцам нет. Ведь по идее массив должен располгагаться в памяти последовательно одна строка за другой!
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

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

Сообщение GSerg » 19.07.2003 (Сб) 6:25

Я много раз заходил на vbstreets. Каждый раз мне давали в меру бестолковый совет ;). Один из таких советов - "обрабатывайте массивы в VB сначала по столбцам, затем по строкам, так как VB хранит массивы один столбец за другим, и такое обращение вызовет меньшее количество листания".
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Aquarius
Постоялец
Постоялец
 
Сообщения: 692
Зарегистрирован: 04.11.2002 (Пн) 13:13
Откуда: Russia

Сообщение Aquarius » 19.07.2003 (Сб) 7:12

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

Итог: Спасибо GSerg

ОБРАБАТЫВАЙТЕ МАССИВЫ ПО СТОЛБЦАМ!!!
(Всем изучать ASSEMBLER)
www.Wasm.ru, www.FlatAssembler.Net

ToT
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 124
Зарегистрирован: 10.06.2002 (Пн) 11:56
Откуда: Russia, Taganrog

Сообщение ToT » 19.07.2003 (Сб) 8:05

Ну а что вы хотели, ВБ это ВБ. Я вот например недавно глянул, что он там ассемблирует из-под профайлера и первое, что мне бросилось в глаза, это команды типа mov eax, 00000000 , т.е. никаких тебе кратких форм. Отсуда и размеры экзешников :) Что тут говорить?
Keyboard not found. Press any key.

ToT
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 124
Зарегистрирован: 10.06.2002 (Пн) 11:56
Откуда: Russia, Taganrog

Сообщение ToT » 19.07.2003 (Сб) 8:07

Ну а что вы хотели, ВБ это ВБ. Я вот например недавно глянул, что он там ассемблирует из-под профайлера и первое, что мне бросилось в глаза, это команды типа mov eax, 00000000 , т.е. никаких тебе кратких форм. Отсуда и размеры экзешников :) Что тут говорить?
Keyboard not found. Press any key.

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 20.07.2003 (Вс) 9:42

Aquarius писал(а):
если процессор умножал бы "в столбик"(что очень мало вероятно скорее всего используется алгоритм Шёнхаге-Штрассена) то лишние нули во много сократили бы процесс. Но могут использоватся и похожие алгоритмы

Чтобы узнать что некоторый бит равен нулю, его для начала нужно проверить на ноль. А это уже лишние операции.


GSerg ща проверю. Хотя логики в том чтобы обрабатывать массивы по столбцам нет. Ведь по идее массив должен располгагаться в памяти последовательно одна строка за другой!


Давайте умножим 10000 в столбик на 1111

Код: Выделить всё
        1111
*   10000
------------
             0
           0
         0
       0
     1111
           

Итоги: нам пришлось сложить 4 одноразрядных числа и прибавить  одно четирёх разрядное. 8 операций сложения с битами   

А теперь умножим 1111 на 1111
     1111
*   1111
---------
     1111
   1111
  1111
1111
     
Итоги: нам пришлось сложить четыре четырехзначных числа:

     1111
   1111 
---------
   101101 - пять операций с битами. для сложения четырёх таких чисел надо 5 * 4 = 20 операций(и это не учитывая что число всё время увеличивается)

Tauron
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 187
Зарегистрирован: 14.07.2002 (Вс) 17:43
Откуда: Kazakhstan

Сообщение Tauron » 20.07.2003 (Вс) 16:26

2GoGosha:
А вот и нет. Там где ты написал в первом случае "0" на самом деле будет "0000". Так что ничего от наличия нулей не меняется.
Трезвая голова, холодный ум и ледяное сердце.

GoGosha
Постоялец
Постоялец
 
Сообщения: 642
Зарегистрирован: 02.08.2002 (Пт) 9:14
Откуда: Russia

Сообщение GoGosha » 20.07.2003 (Вс) 16:44

Tauron писал(а):2GoGosha:
А вот и нет. Там где ты написал в первом случае "0" на самом деле будет "0000". Так что ничего от наличия нулей не меняется.


Код: Выделить всё
        0
       00
      000
     0000


     1111
    11110
   111100
  1111000


Лодно всё хватит флудить
http://poetry.mooo.com
http://poetry.myboard.info
«Человек есть нечто, что до́лжно превзойти» (Ф. Ницше)

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 20.07.2003 (Вс) 18:18

GoGosha, тебя наградить за флуд? :) Или может быть еще кого?

Короче, флудеры, отвлеклись вы от темы.
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali


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

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

Сейчас этот форум просматривают: Google-бот, Yandex-бот и гости: 4

    TopList  
cron