5

Arduino環境にあるコードがあり、シフトレジスタコードの実行時に操作可能なx(8刻み)ブール値が必要です。したがって、現在、次のようなブール配列を使用しています。

 #define number_of_shiftRegisters 220 //num of 8 bit shift registers

 #define numOfRegisterPins number_of_shiftRegisters * 8 //number of booleans needed

 boolean registers[numOfRegisterPins]; //boolean array

しかし、RAMが約200(1600ブール)不足していて、ブールが1ビットであっても、8ビットのデータに格納されていることを確認するまでその理由がわかりませんでした。

前に言ったように、必要なブールの数は常に8の増分であるため、それが私の利点に役立つかどうかはわかりません。

1000以上のブール値を格納し、それでもインデックスでそれらを参照できる、よりメモリ効率の高い方法はありますか?

または...少なくともメモリ効率が高く、設定と反復にCPU時間を大幅に増やす必要はありませんか?

私は配列について考えchar、次に各文字をビットマスキングして個々のビットにアクセスしました。しかし、もっと簡単な方法があるのか​​、それともかなり多くのCPU時間を消費するのかはわかりませんでした。

4

2 に答える 2

6

はい、マスキングを使用してその問題を簡単に回避できます。

values & (1 << i)すべてのバイト(unsigned char)には8つのブール値が含まれ、ifテストで使用できるi番目を取得します。正しいビットが設定されている場合、結果は!=から0になるため機能します。

代わりにビットを設定するには、それをシフトするか、値にシフトします:( values | (1 << i)設定されていない場合は、0とANDする必要があります)。

別の解決策は、パックされた構造体を使用することです。

struct Bools
{
  int b1 : 1;
  int b2 : 1;
  int b3 : 1;
  ... // up to b8
}

これにより、ブール値に直接アクセスできる要素を管理し、ユニオンを定義して、それらを8つのシングルビットブール値またはバイトとして管理できるようにする必要があります。

于 2011-04-10T13:57:08.887 に答える
3

メモリ効率を高めることも、計算効率を高めることもできますが、両方を同時に持つことはできません。

ブール値を配列にパックunsigned charするということは、ランダムな読み取りアクセスの場合、次のことを行う必要があることを意味します。

  1. ビットが存在する配列へのオフセットを計算します
  2. その要素を取得する
  3. 興味のあるビットが存在するバイトへのオフセットを計算します
  4. バイトをその回数だけシフトして、ビットを最下位の位置に配置します
  5. 最も重要でない位置を除くすべてをマスクします
  6. ゼロ/非ゼロをテストします

それらを個々の配列要素に格納すると、次のようになります。

  1. 関心のあるブール値を含む要素を取得します
  2. ゼロ/非ゼロをテストします

どちらを選択するかは、ストレージとパフォーマンスのニーズが互いにどのようにバランスするか、データをどのように使用するか、およびどのようなトレードオフを行うかによって異なります。あなたの場合、直接アクセスするアプローチでは、ストレージが8倍に増加し、メモリが不足して障害が発生するため、テーブルから外れます。そのため、追加の処理が必要になり、パックされたビットが残ります。

セットの全部または一部を反復処理するのに多くの時間を費やす場合は、パックされたアプローチを使用して、必要なときにのみバイトを取得し、後を追うたびに1つのシフトとマスクを実行することで、計算の一部を削減できます。次のビット。 これをすぐに行うと、最適化が時期尚早になるため、アクセスが実際にボトルネックを引き起こしていることがわかるまで、バックポケットに入れておいてください。最初に使用可能なメモリを実行するようにプログラムを取得します。

また、Arduinoで使用されているマイクロコントローラーは特に洗練されておらず、大きなレジスターを備えていないため、より大きなものに詰め込むと、生産性が向上unsigned intするunsigned long可能性があることにも注意してください。

于 2011-04-10T15:05:53.543 に答える