GCC rychle kopirovani pameti
Miroslav Mraz
mrazik na volny.cz
Neděle Červen 10 14:19:19 CEST 2018
Letmý pohled do zdrojáků memcpy v newlib a pár pokusů odhalí příčinu.
1. Knihovna newlib musí být optimalizována na rychlost. Pokud např.
používáte --specs=nano.specs, pak se bude kopírovat byte po byte vždy.
2. Optimálně jsou kopírovány jen bloky delší než 16 (resp. 64) bytů.
3. Začátek jak zdrojového, tak cílového operandu musí být zarovnán na 4
byte. To není zcela samozřejmé i když samotná délka operandů v bytech je
dělitelná 4. Ten linker s tím může dělat různé pitomosti podle nastavení
a struktury prostě nezarovná. V GCC je poměrně dobré udělat něco jako
struct foo {
uint8_t a [100];
}__attribute__((aligned(4)));
Tohle se dost dobře osvědčilo, některé algoritmy se dají takto zrychlit
několika násobně. Jsem líný to měřit, ale předpokládám, že to zabere i u
toho memcpy() a asi lépe než tím vaším programem.
Na CM3/4 se dá pracovat pomocí ldr a str i s celým 32.bitovým slovem,
které nemusí být zarovnáno, ale patrně to bude o něco pomalejší než když
to slovo zarovnané je. Kompetentněji by se k tomu musel vyjádřit asi
někdo lépe obeznámený s architekturou ARM (wek), já jen vím, že na CM0
to spolehlivě zbuchne na unaligned access.
Mrazík
Dne 9.6.2018 v 11:20 Jaroslav Buchta napsal(a):
> To je mi jasne, ze ten kod neni univerzalni ale je to urceno specialne
> pro kopirovani jedne struktury dlouhe cca 100B v casove kriticke ISR ,
> ktera je zarovnana na 4B a tim padem OK. Predpokladam tedy, ze
> instrukcim ldrd a strd neni potreba zarovnat adresu modulo 8 ? Ten druhy
> while ma byt samozrejme take if, ale prelozi se to stejne. memcpy trvalo
> tusim pres 10us a tato funkce to zvladne pod 3us (STM32F3)
>
Další informace o konferenci Hw-list