Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.11.2010, 12:18   #1
basil0
 
Аватар для basil0
 
Регистрация: 23.11.2010
Сообщений: 5
Вопрос Оптимизация времени исполнения макроса

Здравствуйте!
Я пишу макрос (первый раз; только для себя и пары коллег) моделирующий поведение рыб методом Монте-Карло. Основная процедура повторятся сотни миллионов раз, поэтому время выполнения критично.
У меня два вопроса.
1. Надо в макросе Excel (XP, 2007) получить значение системного времени.
Я пока нашел такое
Код:
m=Time
 Секунда_начала=Second(m)+Minute(m)*60 .......
Проблема в том, что секунда слишком грубо. Судя по Паскалю система может выдать время с точностью до 0.01 сек.
Можно ли в макросе получить системное время точнее?
Или упрощенная формулировка: Можно ли определить разницу между двумя запросами системного времени точнее, чем до секунды, при этом сама единица измерения времени меня не интересует лишь бы была на пару и более порядков меньше секунды?

2. Что будет быстрее исполняться из трех вариантов?
Вариант 1.
Код:
Dim KO(200) as Boolean
.....
For i=1 to nTakt
    For n to nRyb 
    KO(n)=True
    Next n
    ........
    For n=1 to nRyb
    If KO(n) and (Distancia (n)<DistAtak) Then
        ........
     KO(n)=False
     endIf
    Next n
 Next i
....
Вариант 2.
Код:
Dim koor(200,4) as Single
.....
For i=1 to nTakt
    For n to nRyb 
    koor(n,4)=0
    Next n
    ........
    For n=1 to nRyb
    If (koor(n,4)=0) and (Distancia (n)<DistAtak) Then
        ........
     (koor(n,4)=1
     endIf
    Next n
 Next i
....
Вариант 3.
Код:
Dim Ryba (200) as .. ' массив объектов или записей с полем Ryba.drak as Boolean 
 .....
For i=1 to nTakt
    For n to nRyb 
    Ryba.drak(n)=True ' Пардон, точный синтаксис обращения к полю элемента массива объектов или записей еще не знаю 
   Next n
    ........
    For n=1 to nRyb
    If Ryba.drak(n) and (Distancia (n)<DistAtak) Then
        ........
     Ryba.drak(n)=False
     endIf
    Next n
 Next i
....
Спасибо.
С уважением, Василий

Последний раз редактировалось basil0; 23.11.2010 в 12:29. Причина: некрасивое отображение примечаний в коде
basil0 вне форума Ответить с цитированием
Старый 23.11.2010, 12:22   #2
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Время обычно упрощённо меряют так:

tm=Timer
...
код, время работы которого замеряем
...
время=Timer-tm
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 23.11.2010, 12:23   #3
VictorM
Старожил
 
Аватар для VictorM
 
Регистрация: 15.05.2008
Сообщений: 2,058
По умолчанию

Цитата:
Можно ли определить разницу между двумя запросами системного времени точнее, чем до секунды,
есть вот такой код:
Цитата:
Для того, чтобы определить сколько милисекунд выполнялся необходимый макрос, достаточно воспользоваться нижеприведённой функцией WinAPI
Код:
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long 

Private Sub YourMacro() 
    iMlSeconds& = GetTickCount 

    'Здесь должен быть код Вашей программы. 

    MsgBox "Время выполнения макроса составило " & _ 
    GetTickCount - iMlSeconds& & " милисек.", vbExclamation, "" 
End Sub
Код взят ОТСЮДА
"Дайте людям рыбы, и вы накормите их на весь день; научите их ловить рыбу - и вы накормите их на всю жизнь"
"Большое спасибо" - Z261597841314, R208907249777, U447361470499
VictorM вне форума Ответить с цитированием
Старый 23.11.2010, 12:26   #4
VictorM
Старожил
 
Аватар для VictorM
 
Регистрация: 15.05.2008
Сообщений: 2,058
По умолчанию

Цитата:
Что будет быстрее исполняться из трех вариантов?
Попробуйте сравнить время выполнения с применеием вышеприведенных кодов на Вашем массиве данных.
"Дайте людям рыбы, и вы накормите их на весь день; научите их ловить рыбу - и вы накормите их на всю жизнь"
"Большое спасибо" - Z261597841314, R208907249777, U447361470499
VictorM вне форума Ответить с цитированием
Старый 23.11.2010, 13:01   #5
SAS888
Старожил
 
Аватар для SAS888
 
Регистрация: 05.12.2007
Сообщений: 4,180
По умолчанию

Цитата:
Что будет быстрее исполняться из трех вариантов?
В любом случае, конструкция
Код:
If [условие1] And [условие2] Then
    '''
End If
будет выполняться медленнее, чем
Код:
If [условие1] Then
    If [условие2] Then
        '''
    End If
End If
ибо для того, чтобы принять решение по логическому And, необходимо всегда проверять оба условия, т.е. для каждого получать True или False, а уже затем делать между ними And. Что в Вашем коде и делается.
Предлагаемый вариант, не смотря на более громоздкую запись, будет выполняться быстрее, т.к. второе условие будет проверяться только при выполнении 1-го. К тому же операция And вообще отсутствует.
Чем шире угол зрения, тем он тупее.
SAS888 вне форума Ответить с цитированием
Старый 23.11.2010, 13:21   #6
Skif-F
Форумчанин
 
Регистрация: 24.03.2010
Сообщений: 349
По умолчанию

Откажитесь от использования типа Single в пользу Integer.
Тип Boolean в массивах - тоже не лучшее решение (меняйте на Integer).
Если требуется скорость, не используйте массивы объектов и даже выражение:

Dim a(200,4) as Integer

если Вы не используете обращение через переменную, лучше заменить на:

Dim a1(200) as Integer, a2(200) as Integer, a3(200) as Integer, a4(200) as Integer

в общем, так:
Код:
Dim koor1(200) as Integer, koor2(200) as Integer, koor3(200) as Integer, koor4(200) as Integer
.....
For i=1 to nTakt
    For n to nRyb 
        koor4(n)=0
    Next n
    ........
    For n=1 to nRyb
        If koor4(n)=0 Then
            If Distancia (n)<DistAtak Then
                 ........
                 koor4(n)=1
            End If
        End If
    Next n
 Next i
Нет нерешаемых задач - есть недостаток времени и данных!
Skif-F вне форума Ответить с цитированием
Старый 23.11.2010, 14:37   #7
basil0
 
Аватар для basil0
 
Регистрация: 23.11.2010
Сообщений: 5
По умолчанию

По предварительным экспериментам Timer чаще работает медленнее (приблизительно на 0.000001 сек), чем GetTickCount, однако разница недостоверна.
Тем не менее инструмент для оценки производительности найден с Вашей помощью, спасибо!

Замена Single на Integer и двумерных массивов на одномерные понятна и логична. Также понятна и замена одного If-а с and на два.
А вот замену Boolean на Integer ИМХО надо еще проверить, т.к. при Integer появляется лишняя операция сравнения с 0.
If i%<0 , но If b (если b - Boolean)

P.S. Хороший комп гробит программиста - сколько же я забыл элементарных вещей со времен DOS-a и 64 кВт оперативки
С уважением, Василий
basil0 вне форума Ответить с цитированием
Старый 23.11.2010, 15:15   #8
Skif-F
Форумчанин
 
Регистрация: 24.03.2010
Сообщений: 349
По умолчанию

Ну что же, Вы меня убедили.
Сделал два теста:
Код:
Sub A()
    Dim A As Integer, i As Long, s As Double
    
    s = Timer
    
    A = 0
    For i = 1 To 10000000
        If A = 1 Then
            A = 0
        Else
            A = 1
        End If
    Next i
    s = Timer - s
End Sub

Sub A2()
    Dim A As Boolean, i As Long, s As Double
    
    s = Timer
    
    A = True
    For i = 1 To 10000000
        If A Then
            A = False
        Else
            A = True
        End If
    Next i
    s = Timer - s
End Sub
Вариан с Integer у меня выполняется за 0,37 сек, а вариант с Boolean - за 0,29 сек. Пробуйте! Потом расскажете.

Однако, однажды мне потребовалось создать массив из 1'000'000, кажется, элементов (возможно больше). Хотел сделать массив Boolean - Excel выдал ошибку "недостаточно память", пришлось делать на Integer
Нет нерешаемых задач - есть недостаток времени и данных!
Skif-F вне форума Ответить с цитированием
Старый 23.11.2010, 15:34   #9
vikttur
Участник клуба
 
Регистрация: 16.05.2010
Сообщений: 1,249
По умолчанию

Цитата:
Сообщение от Skif-F
Хотел сделать массив Boolean - Excel выдал ошибку "недостаточно память", пришлось делать на Integer
Странно, ведь Boolean - только два значения, Integer - 65537
значений. Может быть, ошибка другим вызвана?
vikttur вне форума Ответить с цитированием
Старый 23.11.2010, 15:40   #10
Skif-F
Форумчанин
 
Регистрация: 24.03.2010
Сообщений: 349
По умолчанию

Цитата:
Сообщение от vikttur Посмотреть сообщение
Странно, ведь Boolean - только два значения, Integer - 65537
значений. Может быть, ошибка другим вызвана?
А как VBA хранит булевы переменные? Навряд ли выделяется 1 бит на 1 значение (это вам не Spectrum, где это было обосновано). Поскольку процессоры нонче 32-разрядные, а обращение к биту равносильно обращению к слову (если не дольше), то...

Хотя, возможно, это просто программное ограничение
Нет нерешаемых задач - есть недостаток времени и данных!
Skif-F вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
работа макроса во времени (вопрс новичка) zander Microsoft Office Excel 1 19.08.2010 17:23
Создание во время исполнения xakkkkker Общие вопросы Delphi 0 20.05.2010 17:46
оптимизация времени willhunting Фриланс 10 05.05.2010 10:43
информирование пользователя о % исполнения ADSoft JavaScript, Ajax 2 01.12.2009 03:14
оптимизация для меньшения времени выполнения Ganmaker Паскаль, Turbo Pascal, PascalABC.NET 3 19.11.2008 17:33