На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
  
> Безопасность vs Производительность. , Работа со множеством массивов равного размера.
    У меня задача:
    В проекте может быть множество Single массивов, все одинакового размера. С массивами выполняются разнообразные простые операции, например, массивы можно почленно сложить или перемножить.
    Эти действия оформлены в отдельные процедуры. Крайне желательно, чтобы при наборе кода, использующего процедуры, работал IntelliSense, и чтобы процедуры не принимали параметром другие Single массивы.
    Я обернул массив в тип:
    ExpandedWrap disabled
      Public Type tTF
        Ar() As Single
      End Type

    Так выглядит процедура сложения массивов:
    ExpandedWrap disabled
      Public Sub tTFAdd(Dst As tTF, Src1 As tTF, Src2 As tTF)
        Dim i As Long
       
        For i = 0 To TFSize - 1
          Dst.Ar(i) = Src1.Ar(i) + Src2.Ar(i)
        Next i
      End Sub

    TFSize, как нетрудно догадаться, это общий размер массивов.
    Работает быстро, ничего лишнего в процедуру не подсунешь, но такой подход вынуждает каждый массив инициализировать:
    ExpandedWrap disabled
      Public Sub tTFNew(T As tTF)
        ReDim T.Ar(TFSize - 1)
      End Sub

    Эту инициализацию можно случайно пропустить - получим ошибку. Я мог бы в типе указать сразу фиксированный размер массива, но VB6 не даёт задавать в типе фиксированный размер более 64 Кб, что крайне мало.
    Тогда я решил завернуть массивы не в тип, а в класс. Но в классе нельзя сделать Public массив, приходится делать свойство для доступа к элементам массива. Защищенность повысилась, теперь массив инициализируется автоматически, но скорость упала в 35-40 раз, а для меня этот параметр очень важен.
    Подскажите, есть ли ещё какой-то путь решения моей задачи, который я упустил?
    Прилагаю тестовый проект: Прикреплённый файлПрикреплённый файлSpdTest.zip (6,06 Кбайт, скачиваний: 48)
      Цитата Mikle @
      такой подход вынуждает каждый массив инициализировать

      Ну потому что подход - ущербный. Попробуй нечто вроде вот такого:

      ExpandedWrap disabled
        Public Function tTFAdd(Dst As tTF, Src1 As tTF, Src2 As tTF) As Boolean
          Dim i As Long
          Dim arSize As Long
          
          On Error Goto ErrorHandler
         
          tTFAdd = False
          arSize = Ubound(Src1.Ar)
          If arSize <> Ubound(Src2.Ar) Then Exit Function
        ' removed  If arSize <> Ubound(Dst.Ar) Then
            ReDim Dst.Ar(arSize - 1)
        ' removed  End If
          For i = 0 To arSize - 1
            Dst.Ar(i) = Src1.Ar(i) + Src2.Ar(i)
          Next i
         
          tTFAdd = True
          Exit Function
         
        ErrorHandler:
          Err.Clear
         
        End Function


      Во-первых, контроль равности исходных массивов. Во-вторых, переопределение при необходимости массива-приёмника. В третьих, возвращаемое значение позволяет убедиться, что процесс прошёл нормально, и результат корректен.
      Сообщение отредактировано: Akina -
        Пока массив не инициализирован, Ubound не сработает, поможет ли On Error? надо будет проверить, я включаю оптимизацию "Remove Array Bounds Checks", при такой работе с массивами это немалая прибавка скорости.
        И таких процедур будут десятки, с разным кол-вом аргументов-массивов, и в каждом делать такую проверку... впрочем её можно вынести в процедуру проверки с переменным числом аргументов.
          Цитата Mikle @
          Пока массив не инициализирован, Ubound не сработает

          С другой стороны, содержимое массива назначения по-любому потеряется, есть оно или нет его... может, вместо проверки на размерность делать безусловный ReDim? См. поправленный код.
            Цитата Akina @
            может, вместо проверки на размерность делать безусловный ReDim?

            Для приёмника сгодится, а для источников? А если приёмник так же является одним из источников?
            Вообще, в идеале, было бы хорошо иметь возможность менять TFSize в середине программы, так, чтобы размер всех массивов при этом тоже менялся, пусть с потерей данных. Вижу это в случае, когда массив обёрнут в класс, класс в Initialise автоматически регистрируется в некой коллекции, для смены TFSize есть процедура TFReSize (общая, в модуле), эта процедура проходит по коллекции и редимит все массивы. Если создавать классы-массивы As New, то дальше всё работает красиво, автоматически и без излишеств, только вот вопрос быстродействия остаётся. Можно, разве что, с помощью CopyMemory (или с помощью Friend процедуры в классе, возвращающей массив) дублировать массивы в модуль, но это тоже как-то некрасиво и много лишних телодвижений.
              Попробовал CopyMemory, потеря быстродействия более, чем вдвое. Проект прилагаю:
              Прикреплённый файлПрикреплённый файлSpdTest2.zip (6,78 Кбайт, скачиваний: 80)
                Цитата Mikle @
                А если приёмник так же является одним из источников?

                Добавить проверку, что аргументы не ссылаются на один и тот же массив. Проще отказаться от такой "экономии", чем хлебать проблемы полной ложкой.
                  Нашёл приемлемое решение, без трюков не обошлось, но, вроде бы, получилось безопасно, по крайней мере программа работает в EXE со всеми оптимизациями и в отладчике, выдерживает Stop. Память не течёт.
                  По сравнению с массивом в модуле теряется где-то 8% быстродействия:
                  Прикреплённый файлПрикреплённый файлSpdTest3.zip (6,5 Кбайт, скачиваний: 69)
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0515 ]   [ 22 queries used ]   [ Generated: 28.03.24, 22:07 GMT ]