Easyelectronics.ru • Просмотр темы - Скорость memcpy

Easyelectronics.ru

Электроника для всех
Текущее время: 15 авг 2018, 06:01

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



    • JLCPCB - Прототипы 10 PCBs всего за 2$ (100*100mm, 2-layer)
    • Как мы делаем платы, смотрите на YouTube
    • Крупнейшая китайская фабрика прототипов. 300000+ заказчиков и 10000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин комплектующих.

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

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 32
Всем привет. Как известно, код в прерываниях должен быть максимально быстрым. Допустим через 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
Сообщения: 1671
Откуда: Харьков
С циклом как минимум быстрее из-за отсутствия входа в функцию.
А вообще ХЗ что там внутри этой memcpy. Но я когда-то замерял такты, жрет она прилично.


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

Зарегистрирован: 10 окт 2014, 00:48
Сообщения: 4639
Код:
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
Сообщения: 1371
Есть волшебное окно - Disassembler Window
Там всё показано и разжевано.
А так же есть DWT для сравнения тактов.


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

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 1897
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
Сообщения: 1371
Оно как то msg->Data попало. Если минизировать, то раньше надо начинать оптимизацию.


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

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 32
Если смотреть по 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
Сообщения: 4639
Код:
(msg->Data[0] << 8) + msg->Data[1]

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


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

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 601
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
Сообщения: 32
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
Сообщения: 601
forker писал(а):
Да, нужно наоборот. Поменял, результат аналогичный. Memcpy быстрее.

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


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

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

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


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

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1125
Откуда: Германия
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
Сообщения: 601
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
Сообщения: 2098
Посоны, DMA memory-to-memory в помощь


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

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

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

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


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

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

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


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

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

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

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


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

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

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

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


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

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


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

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

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

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