Цитата(juvf @ Jun 21 2018, 07:24)

Как вы можете знать, как работает memcpy() у ТС, если memcpy реализуется разработчиками каждого компилятора под каждую архитектуру? Вы знаете как каждый memcpy() реализован? У каждого своя реализация.
"из кода видно, что с вероятностью близкой к 100..." где-то я это уже слышал недавно?
Так вот - у ТС-а IAR, и я им пользуюсь; у ТС-а (согласно строки выше) Cortex-M - и я под него сейчас отлаживаю. Аргументов достаточно?
Цитата(juvf @ Jun 21 2018, 07:24)

Как правило, memcpy() реализован так, что из всех возможных реализаций код memcpy будет самый оптимальный, вплоть до ухода в асм. Если пользователь компилятора/библиотеки и решит написать свой копипаст, то он будет менее эффективный, в лучшем случае будет такойже, поэтому при копировании памяти не нужно замарачиваться и изобретать скоростной велосипед, а просто использовать memcpy().
С этим категорически не согласен! Попробуйте когда-нить не теоретизировать внустую, а скомпилировать и посмотреть разные варианты с копированием в цикле
на разных компиляторах с
включённой полной оптимизацией по скорости и с разными условиями цикла (короткий цикл/длинный, условия окончания и указатели - переменные или известны на этапе компиляции). И будете удивлены.
Вариант с memcpy() на коротких циклах, где кол-во проходов и/или указатели заданы переменными, проиграет варианту с простым for, так как ему не надо: a) сохранять содержимое из scratch регистров; б) делать вызов memcpy() и возврат; в) внутри memcpy() выполнять ветвление выбирая нужный вариант цикла копирования по условию длины цикла, выравниваний первого и второго аргумента и т.п.
На циклах с заранее (на этапе компиляции) известными условиями выполнения, for-вариант опять же будет
как минимум не хуже, просто хотя-бы потому что компилятор зная условия выполнения цикла может подставить нужную последовательность команд (подобную оптимальному копированию внутри memcpy()), но с другими более удобными регистрами и их количеством - удобными для данной точки кода.
А некоторые компиляторы, так и вообще цикл for так оптимизируют (при определённых условиях) что готовому memcpy() и не снилось - в разы быстрее по скорости. Смотрим на компиляторы для DSP-ядер.
Цитата(juvf @ Jun 21 2018, 07:24)

Посмотрите сколько лишних операций в for у ТС! какие-то приведения типов, операторы, << и |, дополнительный j, операции j++!!! УЖАС!!!
И что? Современные оптимизаторы творят чудеса. И им по-барабану Ваши жалкие потуги заменить операции индексирования на указатели и подобное - они это и сами хорошо делают, даже ещё и лучше. Так что если бы код автора не был такой кривой, результат работы оптимизирующего компилятора мог быть лучше memcpy().
Я в своё время, разрабатывая для DSP, немало заменил копирований через memcpy() на циклы for - это давало внушительный прирост скорости.
Цитата(juvf @ Jun 21 2018, 07:24)

(кстати.... j++ достаточно медленный, по сравнению с ++j).
Опять чушь! Если предположить, что автор использует ARM, то что пре- что пост-инкремент - без разницы, и то и другое на ARM можно сделать в пределах одной команды выборки из памяти. Откройте мануал по системе команд и найдите разницу между:
LDRB Rx, [Ry], #1 и
LDRB Rx, [Ry, #1]!Цитата(juvf @ Jun 21 2018, 07:24)

В каких случаях? какие неточности?
Во-первых: memcpy там не к месту как я писал выше;
во-вторых: ничего не известно о значении
size_to_take, а если она перед началом цикла может быть отрицательной (и i - тоже знаковое), что будет с вашим вариантом на memcpy()?
в-3-х: с чего Вы приводите входные аргументы к типу void *? А если у ТС-а DataBuffer и data_out объявлены к примеру с модификатором
volatile, т.е. указывают на strong ordered memory? Например DataBuffer или data_out - это FIFO-буфера в некоей периферии, чувствительные к размерности и последовательности операций записи/чтения.
Я уж не говорю о том, что эта память может позволять только доступы определённой разрядности...
Цитата(juvf @ Jun 21 2018, 07:24)

вы сами себе противоречите, причем сразу в одном посте.....
В чём именно противоречие?

Цитата(adnega @ Jun 21 2018, 08:32)

Если по исходнику понятно, что источник шире 8 байт приведет к перемешиванию бит, а в приемнике в итоге получается только 16 значащих бит,
то с уверенностью можно принять за факт их размеры 8 и 16 бит соответственно, и при необходимости заявлять "сам дурак",
Из "исходника" даже не ясно, что именно нужно этому горе-программисту (если data_out указывает на unsigned char) - поменять местами байты при копировании или может он хочет продублировать байты. Т.е. сделать так:
1.
*(u16 *)&DataBuffer[i] = __REVSH(*(u16 __packed *)&data_out[j]); j += 2;или так:
2.
*(u16 *)&DataBuffer[i] = (uint)*(u8 *)&data_out[j++] * 0x101u;а может и что другое.....