Просмотр полной версии : Работа с массивами
Как обнулить значения всех элементов массива без циклов?
Как присвоить массиву из 100 элементов, значения двух массивов по 50 элементов, подряд?
Логвиненко Андрей
22.06.2011, 07:27
Посмотрите библиотеку SysLibMem.
Александр Приходько
22.06.2011, 12:44
Как обнулить значения всех элементов массива без циклов?
Как присвоить массиву из 100 элементов, значения двух массивов по 50 элементов, подряд?
Необходимо учиться работать с памятью и указателями.
Если это непосильно сложно, то все просто:
FOR i:=0 to 99 do
if i <50 then
a[i]:=b[i];
else
a[i]:=c[i-50];
END_IF
END_FOR
где а - ваш массив, b и с два других.
Serge_UA
22.06.2011, 19:25
Как обнулить значения всех элементов массива без циклов?
Функцией SysMemSet из библиотеки SysLibMem.
myArray: ARRAY [0..100] OF REAL;
SysMemSet(dwDest:=ADR(myArray), bCharacter:= 0, dwCount:= SIZEOF(myArray));
Как присвоить массиву из 100 элементов, значения двух массивов по 50 элементов, подряд?
Двумя вызовами функции SysMemMove из библиотеки SysLibMem. По аналогии с примером выше.
Подсказка: для второго вызова SysMemMove параметр dwDest равен ADR(myArray) + SIZEOF(Array_50_1)
2 Предыдущим ораторам:
Описание указателей в CodeSys и библиотеки SysLibMem настолько скудное, что складывается впечатление, что разработчики CodeSys ненавидят программистов ПЛК.
Serge_UA
22.06.2011, 21:50
:) А вот другие немецкие разработчики (oscat) предлагают неплохой набор функций по работе с массивами
...реализованных на циклах и поэтому в десятки-сотни раз медленней, чем аналоги на SysMemLib
Serge_UA
23.06.2011, 09:32
Да уж и не докажешь что SysLibMem использует тоже цикл, да и ADR вместе с SIZEOF тоже без них необходятся. А чем кстати проверяли время в обоих случаях или чисто теория
Проверял экспериментально в PLCWinNT. Я уверен что SysLibMem написана не на ST, поэтому " ADR вместе с SIZEOF" он точно не использует :)
Написана либо на ассемблере, либо на С. Но "местные" вам точнее скажут :)
Логвиненко Андрей
23.06.2011, 11:55
Справка CoDeSys:
Системные библиотеки дают доступ к специализированным и низкоуровневым функциям контроллера. Набор доступных библиотек зависит от аппаратной платформы.
Я это понимаю так, что системные библиотеки реализованы в непосредственно в прошивке контроллера, открыв библиотеку в CoDeSys мы видим только раздел объявлений входных и выходных переменных, никакого ST нет и в помине.
Логвиненко Андрей
23.06.2011, 12:32
не пойму как перебор данных одного и того же массива может поменять скорость взависимости от метода
Все зависит от оптимальности кода, сгенерированого компилятором.
Давать их обычному пользователю для того чтоб он "глумился" над контроллером никто не даст
Системные библиотеки именно дают возможность глумится над контроллером, поэтому применять их надо осторожно.
Логвиненко Андрей
23.06.2011, 13:14
Для корректной работы необходимо прежде всего представлять последствия действий, связанных с применением системных функций, а также при работе с указателями и прямой адресацией.
если бы мне предоставили те внутренние инструменты которыми оснащена эта библиотека
Пожалуйста:
SysLibMem- разрушение данных и программы в ОЗУ, зависание контроллера из-за нарушения выравнивания данных.
SysLibFile - искажение или уничтожение системных файлов, загрузочного файла проекта, разрушение файловой системы контроллера вплоть до выхода из строя flash-памяти.
SysLibCom - нарушение связи с внешними устройствами , подключенными в конфигураторе через COM-порты.
Serge_UA
23.06.2011, 14:13
Если бы dwDist и dwCount присваивались константы, то конечно, но на их вход подаются функции о которых я писал, выходит что участвуют.
Это, извините, отмазка ;). Никто вам не запрещает присваивать этим параметрам константы, особенно параметру dwCount.
В любом случае, даже если это не так, циклы всеравно существуют
Согласен, ведь процессор 32-разрядный и за один такт оперирует всего 4-мя байтами :D :D :D . Думаю в процессоре существуют аппаратные средства для копирования блоков памяти, обращение к которым осуществляется через инструкции процессора, доступ к которым в CodeSys реализован через обсуждаемую библиотеку. Например, тот же самый DMA.
Все зависит от оптимальности кода, сгенерированого компилятором.
Чесно говоря, не вижу, как можно оптимизировать один простой цикл так, чтобы увеличить производительность на несколько порядков.
Serge_UA
23.06.2011, 14:41
Опаньки ...
:)
Спор ни о чем. Вычислите адрес массива один раз при старте контроллера и используйте эту переменную. Почти константа.
Вот описание (http://www.gaw.ru/html.cgi/txt/publ/_ineltek/at91rm9200.htm)процессора используемого в овене. Если есть желание, можете поискать что-нибудь про копирование блоков памяти.
Вечером выложу свои результаты тестов SysMemLib.
Логвиненко Андрей
23.06.2011, 14:55
Вот мой тест , разница по времени более чем на порядок, чего и следовало ожидать.
Логвиненко Андрей
23.06.2011, 15:52
Передача 32767 байт в цикле -100 мс, через SysMemSet - 7 мс.
Логвиненко Андрей
23.06.2011, 16:18
Эмулятор не показатель, а в PLCWinNT оба варианта дают менее 1 мс
Serge_UA
23.06.2011, 17:40
Эмулятор не показатель
SysMemLib это внешняя библиотека. А внешние библиотеки не работают на эмуляторе.
Serge_UA
23.06.2011, 18:06
Мой тест
Методика:
Код выполнялся в 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 мс.
FOR j:= 1 TO ITERATIONS_NUMBER DO
SysMemMove(dwDest:=ADR(destination),
dwSrc:=ADR(source), dwCount:=MAX_ELEMENT+1);
END_FOR
Код №2. Используется косвенная адрессация через указатели
Время выполнения 7856 мс.
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
Код №3. Используется адресация по индексу в массиве
Время выполнения 3860 мс.
FOR j:= 1 TO ITERATIONS_NUMBER DO
FOR i:= 0 TO MAX_ELEMENT DO
destination[i] := source[i];
END_FOR
END_FOR
Цикл по j во всех вариантах добавлен для увеличения точности измерения.
Комментарии и критика "чистоты эксперимента" приветствуются. :)
Serge_UA
23.06.2011, 18:32
Вот проект с тестом
Логвиненко Андрей
23.06.2011, 21:12
SysMemLib это внешняя библиотека. А внешние библиотеки не работают на эмуляторе.
И я про это, только термины Вы попутали:
Порядок программирования контроллеров семейства ПЛК1хх (ПЛК100, ПЛК150, ПЛК154, ПЛК110):
External Library (внутренние библиотеки) – это библиотеки, исполняемый код которых содержится в ядре внутреннего программного обеспечения контроллера. Это, как правило, системные библиотеки, реализовывающие связь со встроенным оборудованием контроллера или библиотеки специального назначения. Данные библиотеки не могут использоваться в режиме эмуляции. Внутренние библиотеки создает производитель контроллера и компания 3S Software – создатель среды CoDeSys. Их список не может быть расширен потребителем.
Мой тест...
А на ПЛК не пробовали?
Serge_UA
23.06.2011, 21:43
И я про это, только термины Вы попутали
Это не я попутал, это переводчики пролога попутали :D :D :D
External Library - внешняя библиотека (а не внутренняя).
А на ПЛК не пробовали?
Нет. В настоящее время у меня нет доступа к ПЛК.
Спасибо за подробное обсуждение вопроса!
Я где то в глубине разума подозревал, что это можно сделать быстрее чем в цикле, потому и задал вопрос!
Вот только до нужной библиотеки не дошел!
Спасибо всем участникам спора, ибо в споре рождается истина, вследствии более детального изучения проблемы!
:)
Игорь Петров
24.06.2011, 15:25
Это не я попутал, это переводчики пролога попутали
:cool: Будут наказаны за вранье. Кстати, с какого языка они переводили описание ПЛК1хх?
VitSSSSS
01.07.2011, 12:24
Мой тест ...
...
Комментарии и критика "чистоты эксперимента" приветствуются. :)
А такой вариант:
...
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.
?
Serge_UA
02.07.2011, 16:32
А такой вариант:
...
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 мс.
sourcePtr2: POINTER TO ARRAY [0..MAX_ELEMENT] OF BYTE;
FOR j:= 1 TO ITERATIONS_NUMBER DO
sourcePtr2:= ADR(source);
destination:= sourcePtr2^;
END_FOR
Время выполнения точно такое же, как и в варианте с SysMemLib. Подозрительно :cool:. Похоже в этом варианте скрытно вызывается функция sysMemMove(). А результат 32 мс вы получили, потому что выполняли копирование 1 раз, а не в цикле ;).
:cool: Будут наказаны за вранье. Кстати, с какого языка они переводили описание ПЛК1хх?
Не понял, к кому этот вопрос, но на всякий случай отвечу - не знаю. :)
Serge_UA
04.07.2011, 12:09
На Яве когда я провожу отладку кода, время выполнения значительно увеличивается, при отображении значений каждой итерации, в КДС скорее всего тоже самое, вполне возможно что откомпилированный код выполняется одинаково как я раньше и говорил, но если смотреть, то все подобные функции не включающие в себя прямым образом цикл, выполняются быстрее, потому что при циклах КДС как семафор "тормозит" выполнение программы
Возможно. Хотя сомневаюсь. На досуге попробую сделать тест с отключенным от PLCWinNT CodeSyS.
П.С. Что такое Ява? :confused: Симулятор написан на java? Не заметил, чтобы устанавливалась java-runtime при установке CodeSys.
Игорь Петров
04.07.2011, 14:28
Не понял, к кому этот вопрос, но на всякий случай отвечу - не знаю. :)
Увидев Ваше обвинение ‘переводчики Пролога напутали’ я хотел лишить виновного отпускных. Но, следствие доказало что совершенно напрасно. Пожалуйста, пишите ‘не знаю кто напутал’ если не знаете или не уверены.
Serge_UA
04.07.2011, 19:53
Увидев Ваше обвинение ‘переводчики Пролога напутали’ я хотел лишить виновного отпускных. Но, следствие доказало что совершенно напрасно. Пожалуйста, пишите ‘не знаю кто напутал’ если не знаете или не уверены.
Я категорически против лишения кого-либо отпускных. "Обвинил" я исходя из цитаты приведенной Логвиненко Андреем. Я полагал, что она из официального источника :rolleyes: . Тысяча извинений переводчикам Пролога.
Serge_UA
04.07.2011, 19:55
Чтобы закончить следствие, нужно спросить у Логвиненко Андрея откуда скопирована его цитата. :D
Логвиненко Андрей
05.07.2011, 08:00
Не думал, что из-за этого может подняться такой спор, цитата взята отсюда:
"Порядок программирования контроллеров семейства ПЛК1хх (ПЛК100, ПЛК150, ПЛК154, ПЛК110)" стр. 9 с диска ПЛК версия 8.12.
ВениаминШ
30.05.2020, 21:46
Подскажите п-та "чайнику".
Имею массив chan:ARRAY[1..4,1..4] OF WORD, пытаюсь обратиться к элементу массива по индексам содержащимся в переменных row:INT и line:INT, но выражение chan[row,line] выдает ошибку.
Где я ошибаюсь?
Подскажите п-та "чайнику".
Имею массив chan:ARRAY[1..4,1..4] OF WORD, пытаюсь обратиться к элементу массива по индексам содержащимся в переменных row:INT и line:INT, но выражение chan[row,line] выдает ошибку.
Где я ошибаюсь?
какого вида ошибка мы догадываться должны? Может Вы там нулями всё обложили
ВениаминШ
30.05.2020, 22:49
Ошибка выполнения: неверный индекс массива. откройте стек вызовов.
Переменная получается из числа от 0 до 15 деленного на 4 -> (WORD_TO_INT) -> плюс 1 = число int от 1 до 4
ну так в том то и дело, ищите ошибку у себя
У меня нет ошибок
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot