Easyelectronics.ru

Электроника для всех
Текущее время: 21 июн 2018, 23:15

Часовой пояс: UTC + 5 часов



    • JLCPCB - Платы прототипов всего за 2$ c бесплатной доставкой (при первом заказе)
    • 10 PCBs за $2 для 2 слоев, $15 для 4 слойной, $74 для 6 слойной платы.
    • Крупнейший китайский производитель прототипных плат. 290000+ клиентов & 8000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин радиодеталей.

Начать новую тему Ответить на тему  [ Сообщений: 20 ] 
Автор Сообщение
 Заголовок сообщения: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 12:14 
Только пришел

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 29
Всем привет. Как известно, код в прерываниях должен быть максимально быстрым. Допустим через CAN по заданному протоколу приходят данные. В прерывании мы обрабатываем эти данные. Например, приходит 16-битное число, которое нужно сохранить для дальнейшей обработки. Какой вариант кода будет быстрее?

Код:
uint16_t data;
data = (msg->Data[0] << 8) + msg->Data[1];


Или такой вариант:

Код:
uint16_t data;
memcpy(&(msg->Data[0]), &data, 2);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 12:48 
Старожил
Аватара пользователя

Зарегистрирован: 27 мар 2015, 04:10
Сообщения: 1553
Откуда: Харьков
С циклом как минимум быстрее из-за отсутствия входа в функцию.
А вообще ХЗ что там внутри этой memcpy. Но я когда-то замерял такты, жрет она прилично.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 13:07 
Старожил

Зарегистрирован: 10 окт 2014, 00:48
Сообщения: 4486
Код:
uint16_t Time1,Time2;
uint16_t data;
Time1 = GetTimer();
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
data = (msg->Data[0] << 8) + msg->Data[1];
Time1 = GetTimer() - Time1;
Time2 = GetTimer();
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
memcpy(&(msg->Data[0]), &data, 2);
Time2 = GetTimer() - Time2;
print(Time1>>3,Time2>>3);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 13:31 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1302
Есть волшебное окно - Disassembler Window
Там всё показано и разжевано.
А так же есть DWT для сравнения тактов.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 13:58 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 1692
forker писал(а):
Всем привет. Как известно, код в прерываниях должен быть максимально быстрым. Допустим через CAN по заданному протоколу приходят данные. В прерывании мы обрабатываем эти данные. Например, приходит 16-битное число, которое нужно сохранить для дальнейшей обработки. Какой вариант кода будет быстрее?

Код:
uint16_t data;
data = (msg->Data[0] << 8) + msg->Data[1];


Или такой вариант:

Код:
uint16_t data;
memcpy(&(msg->Data[0]), &data, 2);


Вот такой вариант точно будет быстрее, но не факт, что на выходе будет правильный порядок байтов:

Код:
uint16_t data;
data = *((uint16_t*)msg->Data);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 14:39 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1302
Оно как то msg->Data попало. Если минизировать, то раньше надо начинать оптимизацию.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 15:16 
Только пришел

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 29
Если смотреть по systick счетчику (msg->Data[0] << 8) + msg->Data[1] - 23 единицы времени; memcpy(&(msg->Data[0]), &data, 2) - 16 единиц. Для 5 операций подряд разница примерно в два раза. Memcpy побыстрее будет). Компилятор GCC.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 15:28 
Старожил

Зарегистрирован: 10 окт 2014, 00:48
Сообщения: 4486
Код:
(msg->Data[0] << 8) + msg->Data[1]

Гм, забавная конструкция.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 15:33 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 539
forker писал(а):
Если смотреть по systick счетчику (msg->Data[0] << 8) + msg->Data[1] - 23 единицы времени; memcpy(&(msg->Data[0]), &data, 2) - 16 единиц. Для 5 операций подряд разница примерно в два раза. Memcpy побыстрее будет). Компилятор GCC.

Тебя не смущает, что в первом случае данные копируются в data, а во втором в msg->Data?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 15:49 
Только пришел

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 29
Reflector писал(а):
forker писал(а):
Если смотреть по systick счетчику (msg->Data[0] << 8) + msg->Data[1] - 23 единицы времени; memcpy(&(msg->Data[0]), &data, 2) - 16 единиц. Для 5 операций подряд разница примерно в два раза. Memcpy побыстрее будет). Компилятор GCC.

Тебя не смущает, что в первом случае данные копируются в data, а во втором в msg->Data?


Да, нужно наоборот. Поменял, результат аналогичный. Memcpy быстрее.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 16:04 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 539
forker писал(а):
Да, нужно наоборот. Поменял, результат аналогичный. Memcpy быстрее.

Самый простой вариант предложил evsi. Он может и не быстрее memcpy, но и медленнее тоже быть не должен.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 16:40 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1123
Откуда: Германия
evsi писал(а):
Вот такой вариант точно будет быстрее, но не факт, что на выходе будет правильный порядок байтов:

Код:
uint16_t data;
data = *((uint16_t*)msg->Data);

Такой вариант будет работать гарантированно на 8ми битках. На 16ти и более битных архитектурах будет работать только если начало msg->Data выравненно на "архитектурную" границу. Если нет, то, например, на СТМках будет вываливаться в HardFolt Unaligned access (проверенно). А на некоторых других процах будут неправильные данные.

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 17:10 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 539
MasterAlexei писал(а):
Такой вариант будет работать гарантированно на 8ми битках. На 16ти и более битных архитектурах будет работать только если начало msg->Data выравненно на "архитектурную" границу. Если нет, то, например, на СТМках будет вываливаться в HardFolt Unaligned access (проверенно).

Да, только HardFault будет не на всех STM-ках, а только на Cortex-M0. И все-таки нужно точнее знать что именно TC требуется, может он всегда будет по 2 байта принимать, тогда никаких проблем...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 17:37 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1123
Откуда: Германия
Reflector писал(а):
MasterAlexei писал(а):
Такой вариант будет работать гарантированно на 8ми битках. На 16ти и более битных архитектурах будет работать только если начало msg->Data выравненно на "архитектурную" границу. Если нет, то, например, на СТМках будет вываливаться в HardFolt Unaligned access (проверенно).

Да, только HardFault будет не на всех STM-ках, а только на Cortex-M0. И все-таки нужно точнее знать что именно TC требуется, может он всегда будет по 2 байта принимать, тогда никаких проблем...

У меня прекрасно вылетало и на cortex M3 и на M4 и на M7.
Про "2 байта переслать" - там не важно в сколько, важно начало буфера, а оно может быть не выравнено. И на первой же операции будет выпадать.
Причем, еще момент интересный: если в GCC указать, что хотим использовать минимальную stdlib (-specs=nano.specs) то будет вылетать и при использовании ее "родной" memcpy функции с данными на не выравненном начале, так как вся эта нанолиба скомпилирована без выравнивания (где-то в интере находил про это инфу).

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 18:18 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 539
MasterAlexei писал(а):
У меня прекрасно вылетало и на cortex M3 и на M4 и на M7.

Пишем тест на F303:
Код:
uint8_t buf[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };

uint16_t a = *(uint16_t*)buf;
uint16_t b = *(uint16_t*)&buf[1];
uint16_t c = *(uint16_t*)&buf[2];
uint16_t d = *(uint16_t*)&buf[3];

rtt.printf("%x, %x, %x, %x\n", a, b, c, d);

Результат: 2211, 3322, 4433, 5544

Цитата:
Про "2 байта переслать" - там не важно в сколько, важно начало буфера, а оно может быть не выравнено. И на первой же операции будет выпадать.

Правильно, важно начало буфера, которое выровнять не проблема, а выравнивать его нужно не только чтобы просто работало, а чтобы работало быстро.

Цитата:
Причем, еще момент интересный: если в GCC указать, что хотим использовать минимальную stdlib (-specs=nano.specs) то будет вылетать и при использовании ее "родной" memcpy функции с данными на не выравненном начале, так как вся эта нанолиба скомпилирована без выравнивания (где-то в интере находил про это инфу).

Это понятно, на memcpy надеяться нельзя, вполне возможно разное поведение можно получить даже с разной оптимизацией.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 20:32 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 1826
Посоны, DMA memory-to-memory в помощь


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 21:09 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1123
Откуда: Германия
Reflector писал(а):
Правильно, важно начало буфера, которое выровнять не проблема, а выравнивать его нужно не только чтобы просто работало, а чтобы работало быстро.

Это бывает не всегда возможно, особенно в хитрых протоколах коммуникации, особенно по радио-интерфейсам, где каждый бит экономят, чтоб меньше времени пересылка была (есть частоты, где время одной посылки ограниченно регуляторами) и также, попутно, меньше жрало энергии. И приняв поток таких вот байтиков, надо выдрать оттуда те самые два байта :)
В общем - примеров таких можно валом найти.
Кстати - ваш пример будет работать, так как компилятор сам подставляет правильные команды в этом случае, так как знает о выравнивании. Там кажется какая то команда чтения из памяти в регистры есть, сейчас точно не вспомню, которую компилятор нано-либы использовал в memcpy, которая (команда) критична к выравниванию данных, и которой пофигу управляющий бит, выключающий проверку в проце на выравнивание.

_________________
Мои поделки
http://www.fun-electronic.net/


Последний раз редактировалось MasterAlexei 24 май 2018, 21:13, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 21:10 
Старожил
Аватара пользователя

Зарегистрирован: 05 фев 2013, 00:58
Сообщения: 2875
Откуда: Тольятти
Возрадуемся, братие, ибо в МК скоро появится BSOD. Думали, ускользнули от всего мелкомягкого в железо? Не тут-то было.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 21:19 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1123
Откуда: Германия
iev91 писал(а):
Возрадуемся, братие, ибо в МК скоро появится BSOD. Думали, ускользнули от всего мелкомягкого в железо? Не тут-то было.

Почему же скоро? Он был/есть уже на кортексах М
По крайней мере, если сделать красивый вывод всей инфы куда либо (на уарт, например) то получится очень даже красивый такой БСОДик.

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Скорость memcpy
СообщениеДобавлено: 24 май 2018, 21:25 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1123
Откуда: Германия
Кстати, мы как-то дебажили memcpy реализацию из библиотеки от Green Hils. (там тоже у нас была проблема с выравниванием, но в момент передачи параметров как (void *) которые потом кастились до u32, но вылечилась контрольным битом, отключавшим такую проверку в проце (AM3515 если что) )

Так вот - там была ассемблерная функция, которая с начала смотрит, выравнено ли начало массива, если нет, то копирует побайтово первые 1-3 байта, потом глядит на последние 1-3 байта, если не выравненны - тоже их побайтово копирует, и только потом уже середину массива по 4е байта на один такт копирует (проц 32х битный).
Так что вполне эффективно все там работало

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 20 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: Fahivec


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB