Otázka:
Vhodnost použití bitových polí ve strukturách
anthropomo
2014-10-01 05:19:12 UTC
view on stackexchange narkive permalink

Musím sledovat velké množství dat (pro Arduino) v programu a současně se starat o spravedlivé množství dalších věcí.

Začal jsem strukturou, jako je tato:

  struct MyStruct {// poznámka: tyto názvy mohou být také foo bar baz uint8_t color; booleovský stav; oblast uint8_t; uint8_t číslo; uint8_t len;};  

Mám jich pole 800. Na 5 bytů je to 4 kB, což je polovina paměti RAM Arduino Mega.

Změnil jsem se na strukturu takto:

  struct MyStruct {uint8_t color: 3; // maximální hodnota 7 // uint8_t state: 1; *** přesunuto, díky Ignacio *** oblast uint8_t: 5; // m.v. 31 uint8_t číslo; uint8_t len: 5; // m.v. 31 uint8_t stát: 1; // m.v. 1};  

Chápu, že to snižuje velikost každé instance na 3 bajty, tedy celkem 2,4 kB v mém poli.

Četl jsem, že v některých implementace / čipové sady využívající bitová pole ve strukturách mohou vést k méně efektivnímu provádění. Je zřejmé, že se jedná o efektivnější využití paměti, ale moje otázka zní:

Jak Arduino zpracovává bitová pole? Bude to lepší, horší nebo zanedbatelně odlišné, pokud jde o rychlost nebo rychlost při iteraci řadou struktur bitových polí? Existuje dobrý způsob, jak to otestovat?

Tato objednávka bude využívat 4 bajty. Získejte toto 1bitové pole z ostatních 8.
@Ignacio Úžasné ... právě jste oholili dalších 9% z mého celkového využití paměti.
Důvodem, proč bitová pole ve strukturách mohou vést k méně efektivnímu provádění, je omezení omezení zarovnání slov. Např. pokud překročí přirozené vyrovnání 32/64, což způsobí více přístupů. To by pro ATmega neměl být problém
Otázku, kterou si musíte položit, je, zda se nejvíc obáváte vyčerpání paměti RAM, programové paměti nebo cyklů CPU - to je situace, kdy můžete optimalizovat docela dost pro jednoho za cenu druhého a nějaký dopad na třetí. V určitém okamžiku byste se měli také zeptat, zda je Arduino založené na ATmega opravdu tou správnou platformou.
Byl jsem schopen restrukturalizovat program tak, aby používal index pole, kde jsem používal 8bitové číslo, takže až 2 bajty na strukturu, dalších 9% oholeno. Vypadá to, že mohu ušetřit cykly. Iteruji 800 struktur každých 50 milisekund a zároveň zpracovávám občasné požadavky HTTP. Žádné problémy. S tímto jsem tlačil limity ATmega, ale zdá se mi, že se dostávám dobře pod.
Zde je několik dalších čtení, ke kterým jsem narazil později: http://www.catb.org/esr/structure-packing/
Tři odpovědi:
jdr5ca
2014-10-01 13:04:39 UTC
view on stackexchange narkive permalink

Čelíte klasickému kompromisu v časové paměti. Bitová pole budou v paměti menší, ale jejich provoz bude trvat déle. Můžete spočítat, že bez ohledu na to, jaký procesor, bitová pole budou pomalejší.

Používáte slovo efektivní , ale toto slovo nemá určitý význam bez metriky toho, co je dobré nebo špatné. Pokud máte pouze 8 k RAM, je používání paměti špatné, čas může být levný. Pokud máte omezení v reálném čase, pak je používání času špatné a paměť může být levná. Obecně si z tohoto kompromisu můžete koupit pouze cestu ven. Jinými slovy, když zjistíte, že je čas i paměť špatné, utratte hotovost a použijte větší čip. Neexistuje jediná odpověď na to, co je dobré nebo špatné. To je část toho, proč existuje tolik možností pro mikrokontroléry, že lidé přizpůsobí čip aplikaci a aplikaci na čip.

Naplnění bitů bitového pole bude pomalejší než vyplňování úplných bajtů. Vezměte například

  x = 5; ... asimplestruct.len = x; // vsabitfield.len = x;  

První jednoduchý případ bude jen:

  • načíst hodnotu x do registru
  • uložit ji do bajtu pro len

Druhý způsobí něco jako:

  • načte aktuální hodnotu abitfieldu
  • načte masku
  • vymaže bity pro len
  • načte aktuální hodnotu x
  • načte masku
  • vymaže nepoužité bity x
  • posune bity x
  • nebo x s abitfieldem
  • ukládá aktuální hodnotu zpět do paměti

Pokud všechny vaše operace shromažďují data do bitového pole nebo se rozbalují z bitového pole, měli byste očekávat pomalejší provádění. Bitová pole jsou typem komprese - stojí za zaškrtnutí.

Ale pohyb po bitových polích bude rychlejší, protože je třeba načíst a uložit méně bytů. Pokud budete toto pole třídit, může být výhodou menší počet bajtů. Pokud je přenášíte přes sériový port, může být vítězem komprimovaná velikost bitového pole.

Takže s ohledem na vaši otázku:

Existuje dobrý způsob, jak to otestovat?

Jediným dobrým způsobem, jak to otestovat, je psát testovací případy pro oba přístupy pomocí vzoru, který úzce odpovídá vaší aplikaci. Opravdu záleží na tom, jakou kombinaci operací provádíte, abyste se rozhodli, zda je rozdíl zanedbatelný nebo významný.

Když provádíte tento druh optimalizačního experimentu, rozhodně použijte u svého projektu řízení zdroje. Místní úložiště GIT nebo Mercurial můžete vytvořit pouhými několika kliknutími. Udržování řetězce kontrolních bodů vám umožní roztrhat váš kód a zkoumat účinky různých implementací. Pokud uděláte špatnou zatáčku, úložiště vám umožní jednoduše se vrátit k poslednímu dobrému bodu a zkusit jinou cestu.

(Poznámka na straně: Tentokrát existuje i kompromis paměti v opačném směru. Pokud se podíváte prostřednictvím možností kompilátoru pro procesory třídy pro stolní počítače najdete něco, co se nazývá strukturované balení . Tato možnost vám umožní přidat prázdné bajty mezi jednobajtová pole tak, aby zůstaly zarovnány na hranici slova nebo dvojitého slova. vypadat šíleně, že úmyslně vyhodí RAM, ale na procesorech s 16 nebo 32 bitovými širokými registry a sběrnicemi mohou být takzvané operace paměti zarovnané na slovo nebo dword rychlejší než operace po bajtech.

JRobert
2014-10-01 22:23:53 UTC
view on stackexchange narkive permalink

Diskuse o bitových polích by nebyla úplná, aniž bychom zmínili, že:

Struktury s bitovými poli lze použít jako přenosný způsob pokusu o zmenšení úložného prostoru požadovaného pro strukturu (s pravděpodobnými náklady na zvětšení prostoru instrukcí a času potřebného pro přístup k polím) nebo jako nepřenosný způsob, jak popsat rozložení úložiště známé na bitové úrovni.

[Kernighan & Ritchie, The C Programming Language, druhé vydání , příloha A-8.3]

Další plakáty, včetně vás, se zabývaly kompromisem časoprostor. Co ale někdy chybí (možná není relevantní pro vaši aplikaci -?) Je úplná závislost implementace rozvržení úložiště . To je důležité, když aplikace sdílejí tato data s jiným procesem: Čtení nebo zápis hardwaru, jehož přiřazení bitů registru je nutně opraveno; komunikace dat do jiného systému (prostřednictvím sítě nebo paměťového zařízení nezáleží); nebo do jiné aplikace ve stejném systému, která mohla být kompilována s jiným kompilátorem nebo verzí kompilátoru.

soerium
2014-10-01 16:26:33 UTC
view on stackexchange narkive permalink

Malý tip - vidím, že struktura není 1B zarovnaná pro 8bitový procesor. Na konci své struktury můžete přidat výplň 2bitovou délku nebo znovu promyslet zvětšení velikosti state….

  struct MyStruct {uint8_t color : 3; // maximální hodnota 7 // uint8_t state: 1; *** přesunuto, díky Ignacio *** oblast uint8_t: 5; // m.v. 31 uint8_t číslo; uint8_t len: 5; // m.v. 31 uint8_t stát: 1; // m.v. 1 uint8_t odsazení: 2;};  
Přidání výplně nezmění dynamickou paměť v době kompilace. Odpusť mi tu moji nevědomost, ale zdá se, že kompilátor se stará o polstrování. Nebo se něco děje za běhu, aby se to vyrovnalo, když nezahrnu výplň?
To je pravda. V tomto případě jde spíše o osvědčený postup.


Tyto otázky a odpovědi byly automaticky přeloženy z anglického jazyka.Původní obsah je k dispozici na webu stackexchange, za který děkujeme za licenci cc by-sa 3.0, pod kterou je distribuován.
Loading...