реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Локальные переменные.
Jenya7
сообщение Jan 20 2015, 11:33
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Прочитал следующее в ARM System Developer's Guide.
Цитата
ARMv4-based processors can efficiently load and store 8-, 16-, and 32-bit data. However,
most ARM data processing operations are 32-bit only. For this reason, you should use
a 32-bit datatype, int or long, for local variables wherever possible. Avoid using char and
short as local variable types, even if you are manipulating an 8- or 16-bit value. The one
exception is when you want wrap-around to occur.

И переделал все локальные переменные на uint32_t.
Вопрос - как я понимаю это касается и аргументов передаваемых в функцию?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 20 2015, 11:36
Сообщение #2


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Jenya7 @ Jan 20 2015, 14:33) *
Прочитал следующее в ARM System Developer's Guide.

И переделал все локальные переменные на uint32_t.
Вопрос - как я понимаю это касается и аргументов передаваемых в функцию?

Да. И возвращаемых значений тоже.
Не касается это лишь управляющих структур, массивов, которые используются в программе. Чтобы место экономить.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 20 2015, 11:42
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 20 2015, 11:50
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(ViKo @ Jan 20 2015, 17:36) *
Да. И возвращаемых значений тоже.
Не касается это лишь управляющих структур, массивов, которые используются в программе. Чтобы место экономить.

Ну а вот например
Код
uint32_t MessageChecksum(unsigned char *p, uint32_t len)
{
    uint32_t csum = 0;
    while (len)
    {
      csum+=(*p)&0xFF;
      p++;
      len--;
    }
    return csum;
}

тут у меня unsigned char потому что это касается UART я передаю данные 8 бит. или все равно привести к uint32_t?

uint_fastXX_t это если я захочу перенести код на AVR sm.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 20 2015, 11:56
Сообщение #5


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Jenya7 @ Jan 20 2015, 14:50) *
тут у меня unsigned char потому что это касается UART я передаю данные 8 бит. или все равно привести к uint32_t?

Конечно, нет. Где нужен char, там должен быть char.
Тем более, вы передаете указатель (32-битовый). rolleyes.gif
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 20 2015, 12:06
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



спасибо. придется засучить рукава. этож тысячи строк кода надо править. sm.gif

Сообщение отредактировал Jenya7 - Jan 20 2015, 12:06
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jan 20 2015, 12:08
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Jenya7 @ Jan 20 2015, 11:50) *
Ну а вот например
Код
uint32_t MessageChecksum(unsigned char *p, uint32_t len)
{
    uint32_t csum = 0;
    while (len)
    {
      csum+=(*p)&0xFF;
      p++;
      len--;
    }
    return csum;
}

тут у меня unsigned char потому что это касается UART я передаю данные 8 бит. или все равно привести к uint32_t?


Если есть ну очень сильное желание, то этот код можно соптимизировать, чтобы он работал с 32-битными значениями. А оно сильно надо ? Этот код критичен к скорости выполнения ?
Да, тогда еще возникнет ряд проблем, если размер массива не будет кратен 4 байтам, придется вводить пляски с бубном. Кроме того, могут возникнуть проблемы с выравниванием всего массива входных данных по границе слова. Если char* автоматически выравнен по границе байта, то uint32* будет выравнен по границе 4-х байтов. Если попытаться вычислить сумму начиная с невыравненного адреса, будут проблемы, в т.ч и с производительностью sm.gif

Общие замечания:
1. в качестве первого параметра надо использовать const unsigned char*, облегчается жизнь себе и компилятору
2. эта контрольная сумма - дерьмо. Она не обнаруживает перестановку байтов, например. Есть гораздо более надежные методы и довольно простые - adler, fletcher checksum, ну и классические CRC

Сообщение отредактировал CrimsonPig - Jan 20 2015, 12:09
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 20 2015, 12:15
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(CrimsonPig @ Jan 20 2015, 18:08) *
Если есть ну очень сильное желание, то этот код можно соптимизировать, чтобы он работал с 32-битными значениями. А оно сильно надо ? Этот код критичен к скорости выполнения ?
Да, тогда еще возникнет ряд проблем, если размер массива не будет кратен 4 байтам, придется вводить пляски с бубном. Кроме того, могут возникнуть проблемы с выравниванием всего массива входных данных по границе слова. Если char* автоматически выравнен по границе байта, то uint32* будет выравнен по границе 4-х байтов. Если попытаться вычислить сумму начиная с невыравненного адреса, будут проблемы, в т.ч и с производительностью sm.gif

Общие замечания:
1. в качестве первого параметра надо использовать const unsigned char*, облегчается жизнь себе и компилятору
2. эта контрольная сумма - дерьмо. Она не обнаруживает перестановку байтов, например. Есть гораздо более надежные методы и довольно простые - adler, fletcher checksum, ну и классические CRC

это poor man CRC - быстро и просто без заморочек.
а вообще прибор работает от батарейки поэтому скорость любой функции для меня важна - быстро отработал и пошел спать.
а чем const упрощает жизнь кроме того что не дает модифицировать строку?

Сообщение отредактировал Jenya7 - Jan 20 2015, 12:17
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jan 20 2015, 12:28
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Jenya7 @ Jan 20 2015, 12:15) *
это poor man CRC - быстро и просто без заморочек.
а вообще прибор работает от батарейки поэтому скорость любой функции для меня важна - быстро отработал и пошел спать.
а чем const упрощает жизнь кроме того что не дает модифицировать строку?


1. "Просто и без заморочек" - это очень хорошо... только вот с обнаружением ошибок будет весьма плохо.
2. про батарейку - вопрос спорный "быстро отработал" - не значит "мало съел". "Скорость любой функции" соптимизировать невозможно. Например, после долгого вырывания волос из попы автор таки соптимизирует свой алгоритм для работы с 32-битными числами. При этом размер кода вырастет в 2 раза, скорость выполнения увеличится на 0.1%, в то время как эта функция как вызывалась раз в секунду, так и вызывается. Оно того стоило ? Все равно потребление электричества надо будет мерять. Не факт что оптимизация по скорости уменьшит потребление энергии.
3. если гениальный автор с бодуна в своей функции напишет не val=*p++, а *p++ = val, и не протестирует (а некоторые вещи почти невозможно протестировать), то впоследствии может быть горько и обидно. Для меня использование const - это как личная гигиена.

Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 20 2015, 12:39
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(CrimsonPig @ Jan 20 2015, 18:28) *
1. "Просто и без заморочек" - это очень хорошо... только вот с обнаружением ошибок будет весьма плохо.
2. про батарейку - вопрос спорный "быстро отработал" - не значит "мало съел". "Скорость любой функции" соптимизировать невозможно. Например, после долгого вырывания волос из попы автор таки соптимизирует свой алгоритм для работы с 32-битными числами. При этом размер кода вырастет в 2 раза, скорость выполнения увеличится на 0.1%, в то время как эта функция как вызывалась раз в секунду, так и вызывается. Оно того стоило ? Все равно потребление электричества надо будет мерять. Не факт что оптимизация по скорости уменьшит потребление энергии.
3. если гениальный автор с бодуна в своей функции напишет не val=*p++, а *p++ = val, и не протестирует (а некоторые вещи почти невозможно протестировать), то впоследствии может быть горько и обидно. Для меня использование const - это как личная гигиена.


Цитата
We saw in Section 5.2.1 that converting local variables from types char or short to type int increases performance and reduces code size.

обратите внимание на reduces code size.
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jan 20 2015, 12:47
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Jenya7 @ Jan 20 2015, 12:39) *
обратите внимание на reduces code size.


Книжки надо не только читать, но еще и понимать.
Например, замена uint_8 на uint_32 в этом примере вполне себе сможет уменьшить размер кода и сделать мир лучше:
for(uint8_t i=0; i<100, ++i)
{ [do something] }

Что будем делать тут?

uint32_t CalcCRC(void* apData, uint32_t aNumBytes);

uint8_t buffer[100];
uint32_t crc = CalcCRC(buffer, 64); //-- очень хорошо, правда ?
crc = CalcCRC(buffer+17, 13); //-- а тут ? Весело? как насчет оптимизации CalcCRC для работы с uint32_t* ?

Сообщение отредактировал CrimsonPig - Jan 20 2015, 12:48
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 20 2015, 12:58
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(CrimsonPig @ Jan 20 2015, 18:47) *
Книжки надо не только читать, но еще и понимать.
Например, замена uint_8 на uint_32 в этом примере вполне себе сможет уменьшить размер кода и сделать мир лучше:
for(uint8_t i=0; i<100, ++i)
{ [do something] }

Что будем делать тут?

uint32_t CalcCRC(void* apData, uint32_t aNumBytes);

uint8_t buffer[100];
uint32_t crc = CalcCRC(buffer, 64); //-- очень хорошо, правда ?
crc = CalcCRC(buffer+17, 13); //-- а тут ? Весело? как насчет оптимизации CalcCRC для работы с uint32_t* ?


нет извините меня. то что вы передаете в функцию в качестве аргумента это ваша ответственность. на то вы и программист.
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jan 20 2015, 13:39
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Jenya7 @ Jan 20 2015, 12:58) *
нет извините меня. то что вы передаете в функцию в качестве аргумента это ваша ответственность. на то вы и программист.


А вот и не извиню, такая я свинья sm.gif если благородный дон вдруг посмотрит на имплементацию нормально написанной функции, типа библиотечной strlen, то он вполне может рассчитывать увидеть там не
while (*p++), а вполне себе развесистый код, который пытается считать длину строки наиболее оптимальным способом с учетом выравнивания данных, учета невыравненных хвостов итп. В общем случае, этот код вообще платформо-зависим для достижения макс. производительности.
При этом strlen не заботит, передают ли ей указатель на выровненные или невыровненные данные.
Опять же, такая оптимизация может быть избыточна. Если всегда работать с правильно выровненными данными, многи вещи становятся проще, правда можно получить exception при попытке поковыряться с байтами в середине буфера sm.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 20 2015, 17:26
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Jenya7 @ Jan 20 2015, 13:50) *
тут у меня unsigned char потому что это касается UART я передаю данные 8 бит.
А складываете вы их всегда в массив unsigned char? И берете всегда из массива unsigned char? Эта функция по идее считает CRC чего угодно. Вот и передавать ей надо "указатель на что угодно", т.е void const *, а внутри заводите уже временную переменную типа "указатель на байт" и присваивайте ей переданный указатель с явным приведением типа. Это позволит написать
Код
typedef struct { ...... } message_t;

message_t Message = {.....};
Checksum = MessageChecksum(&Message, sizeof(Message));
избежав явного приведения типа (unsigned char const *)&Message в большинстве точек вызова. А это разгружает исходник, делая его более легкочитаемым.

Цитата(Jenya7 @ Jan 20 2015, 13:50) *
или все равно привести к uint32_t?
Привести к uint32_t что? Вы передает указатель. От того, на какой тип этот указатель указывает его размер не изменится. А вот если размер ваших сообщений по спецификации протокола не может превышать 255 или 65535 байт, то параметр len имеет смысл делать uint_fast8_t или uint_fast16_t.
Цитата(Jenya7 @ Jan 20 2015, 13:50) *
uint_fastXX_t это если я захочу перенести код на AVR sm.gif
Не обязательно AVR. Вы можете захотеть его перенести на 16- 32- или 64-битную архитектуру, которая умеет делать арифметику с числами 8- или 16-битной разрядности (MSP430 или персоналку). И чтобы этот код и на другой архитектуре тоже был оптимальным без перелопачивания тысяч строк кода, имеет смысл сразу писать его грамотно (или хотя бы стараться писать грамотно).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jan 20 2015, 17:40
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Сергей Борщ @ Jan 20 2015, 17:26) *
А складываете вы их всегда в массив unsigned char? И берете всегда из массива unsigned char? Эта функция по идее считает CRC чего угодно. Вот и передавать ей надо "указатель на что угодно", т.е void const *, а внутри заводите уже временную переменную типа "указатель на байт" и присваивайте ей переданный указатель с явным приведением типа. Это позволит написать


Ик... найдите 3 отличия sm.gif
1. void*
2. const void *
3. void* const
4. const void* const

void Foo(const void* apData), так ведь ? sm.gif
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 15:44
Рейтинг@Mail.ru


Страница сгенерированна за 0.01529 секунд с 7
ELECTRONIX ©2004-2016