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