Как обнулить значения всех элементов массива без циклов?
Как присвоить массиву из 100 элементов, значения двух массивов по 50 элементов, подряд?
Вид для печати
Как обнулить значения всех элементов массива без циклов?
Как присвоить массиву из 100 элементов, значения двух массивов по 50 элементов, подряд?
Посмотрите библиотеку SysLibMem.
Функцией SysMemSet из библиотеки SysLibMem.
Двумя вызовами функции SysMemMove из библиотеки SysLibMem. По аналогии с примером выше.Код:myArray: ARRAY [0..100] OF REAL;
SysMemSet(dwDest:=ADR(myArray), bCharacter:= 0, dwCount:= SIZEOF(myArray));
Подсказка: для второго вызова SysMemMove параметр dwDest равен ADR(myArray) + SIZEOF(Array_50_1)
2 Предыдущим ораторам:
Описание указателей в CodeSys и библиотеки SysLibMem настолько скудное, что складывается впечатление, что разработчики CodeSys ненавидят программистов ПЛК.
Справка CoDeSys:
Я это понимаю так, что системные библиотеки реализованы в непосредственно в прошивке контроллера, открыв библиотеку в CoDeSys мы видим только раздел объявлений входных и выходных переменных, никакого ST нет и в помине.Цитата:
Системные библиотеки дают доступ к специализированным и низкоуровневым функциям контроллера. Набор доступных библиотек зависит от аппаратной платформы.
Все зависит от оптимальности кода, сгенерированого компилятором.Цитата:
не пойму как перебор данных одного и того же массива может поменять скорость взависимости от метода
Системные библиотеки именно дают возможность глумится над контроллером, поэтому применять их надо осторожно.Цитата:
Давать их обычному пользователю для того чтоб он "глумился" над контроллером никто не даст
Для корректной работы необходимо прежде всего представлять последствия действий, связанных с применением системных функций, а также при работе с указателями и прямой адресацией.
Пожалуйста:Цитата:
если бы мне предоставили те внутренние инструменты которыми оснащена эта библиотека
SysLibMem- разрушение данных и программы в ОЗУ, зависание контроллера из-за нарушения выравнивания данных.
SysLibFile - искажение или уничтожение системных файлов, загрузочного файла проекта, разрушение файловой системы контроллера вплоть до выхода из строя flash-памяти.
SysLibCom - нарушение связи с внешними устройствами , подключенными в конфигураторе через COM-порты.
Это, извините, отмазка ;). Никто вам не запрещает присваивать этим параметрам константы, особенно параметру dwCount.
Согласен, ведь процессор 32-разрядный и за один такт оперирует всего 4-мя байтами :D :D :D . Думаю в процессоре существуют аппаратные средства для копирования блоков памяти, обращение к которым осуществляется через инструкции процессора, доступ к которым в CodeSys реализован через обсуждаемую библиотеку. Например, тот же самый DMA.
Чесно говоря, не вижу, как можно оптимизировать один простой цикл так, чтобы увеличить производительность на несколько порядков.
:)
Спор ни о чем. Вычислите адрес массива один раз при старте контроллера и используйте эту переменную. Почти константа.
Вот описание процессора используемого в овене. Если есть желание, можете поискать что-нибудь про копирование блоков памяти.
Вечером выложу свои результаты тестов SysMemLib.
Вот мой тест , разница по времени более чем на порядок, чего и следовало ожидать.
Передача 32767 байт в цикле -100 мс, через SysMemSet - 7 мс.
Эмулятор не показатель, а в PLCWinNT оба варианта дают менее 1 мс
Мой тест
Методика:
Код выполнялся в PLCWinNT v2.4 в freeweeling задаче с отключенным watchdog таймером.
Измерялась длительность одного цикла задачи таймером TON.
Измерения повторялись несколько раз. Разброс результатов 2-5%.
Область объявлений:
Код:VAR CONSTANT
MAX_ELEMENT: INT := 32000;
ITERATIONS_NUMBER: INT:=10000;
END_VAR
VAR
destination: ARRAY [0..MAX_ELEMENT] OF BYTE;
destinationPtr: POINTER TO BYTE;
sourcePtr: POINTER TO BYTE;
source: ARRAY [0..MAX_ELEMENT] OF BYTE := 8, MAX_ELEMENT(8);
i: INT;
j: UDINT;
END_VAR
Код №1. Используется SysMemLib.
Время выполнения 78 мс.
Код №2. Используется косвенная адрессация через указателиКод:FOR j:= 1 TO ITERATIONS_NUMBER DO
SysMemMove(dwDest:=ADR(destination),
dwSrc:=ADR(source), dwCount:=MAX_ELEMENT+1);
END_FOR
Время выполнения 7856 мс.
Код №3. Используется адресация по индексу в массивеКод:FOR j:= 1 TO ITERATIONS_NUMBER DO
sourcePtr:= ADR(source);
destinationPtr:= ADR(destination);
FOR i:= 0 TO MAX_ELEMENT DO
destinationPtr^ := sourcePtr^;
destinationPtr := destinationPtr+1;
sourcePtr:=sourcePtr+1;
END_FOR
END_FOR
Время выполнения 3860 мс.
Цикл по j во всех вариантах добавлен для увеличения точности измерения.Код:FOR j:= 1 TO ITERATIONS_NUMBER DO
FOR i:= 0 TO MAX_ELEMENT DO
destination[i] := source[i];
END_FOR
END_FOR
Комментарии и критика "чистоты эксперимента" приветствуются. :)
Вот проект с тестом
И я про это, только термины Вы попутали:Цитата:
SysMemLib это внешняя библиотека. А внешние библиотеки не работают на эмуляторе.
Цитата:
Порядок программирования контроллеров семейства ПЛК1хх (ПЛК100, ПЛК150, ПЛК154, ПЛК110):
External Library (внутренние библиотеки) – это библиотеки, исполняемый код которых содержится в ядре внутреннего программного обеспечения контроллера. Это, как правило, системные библиотеки, реализовывающие связь со встроенным оборудованием контроллера или библиотеки специального назначения. Данные библиотеки не могут использоваться в режиме эмуляции. Внутренние библиотеки создает производитель контроллера и компания 3S Software – создатель среды CoDeSys. Их список не может быть расширен потребителем.
А на ПЛК не пробовали?Цитата:
Мой тест...
Спасибо за подробное обсуждение вопроса!
Я где то в глубине разума подозревал, что это можно сделать быстрее чем в цикле, потому и задал вопрос!
Вот только до нужной библиотеки не дошел!
Спасибо всем участникам спора, ибо в споре рождается истина, вследствии более детального изучения проблемы!
:)
А такой вариант:
...
VAR
...
source: ARRAY [0..MAX_ELEMENT] OF BYTE := 8, MAX_ELEMENT(8);
destination: ARRAY [0..MAX_ELEMENT] OF BYTE;
sourcePtr: POINTER TO ARRAY [0..MAX_ELEMENT] OF BYTE;
...
END_VAR
Код:
...
2: sourcePtr:= ADR(source);
destination:= sourcePtr^;
...
у меня на компе это за 32ms, а с SysMemLib за 125ms.
?
Этот вариант я исключил из рассмотрения сразу, т.к. размер копируемого блока данных задается в момент компиляции не может быть изменен в процесс выполнения программы. Это, мягко говоря, не удобно.
Но я его протестировал.
Код №4. Используется указатель на массив.
Время выполнения 78 мс.
Время выполнения точно такое же, как и в варианте с SysMemLib. Подозрительно :cool:. Похоже в этом варианте скрытно вызывается функция sysMemMove(). А результат 32 мс вы получили, потому что выполняли копирование 1 раз, а не в цикле ;).Код:sourcePtr2: POINTER TO ARRAY [0..MAX_ELEMENT] OF BYTE;
FOR j:= 1 TO ITERATIONS_NUMBER DO
sourcePtr2:= ADR(source);
destination:= sourcePtr2^;
END_FOR
Не понял, к кому этот вопрос, но на всякий случай отвечу - не знаю. :)
Чтобы закончить следствие, нужно спросить у Логвиненко Андрея откуда скопирована его цитата. :D
Не думал, что из-за этого может подняться такой спор, цитата взята отсюда:
"Порядок программирования контроллеров семейства ПЛК1хх (ПЛК100, ПЛК150, ПЛК154, ПЛК110)" стр. 9 с диска ПЛК версия 8.12.
Подскажите п-та "чайнику".
Имею массив chan:ARRAY[1..4,1..4] OF WORD, пытаюсь обратиться к элементу массива по индексам содержащимся в переменных row:INT и line:INT, но выражение chan[row,line] выдает ошибку.
Где я ошибаюсь?
Ошибка выполнения: неверный индекс массива. откройте стек вызовов.
Переменная получается из числа от 0 до 15 деленного на 4 -> (WORD_TO_INT) -> плюс 1 = число int от 1 до 4
ну так в том то и дело, ищите ошибку у себя
У меня нет ошибок