RAM 效率更高的布尔数组? Arduino环境
我在 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
但是我用完了大约 200 个(1600 个布尔值)的 RAM,直到我看到这一点才知道为什么,即使布尔值是 1 位,它们也存储在 8 位数据中。
正如我之前所说,所需的 bool 数量始终以 8 为增量,所以我不知道这是否对我有利。
是否有一种更有效的内存方式来存储 1000 多个布尔值,并且仍然能够通过索引引用它们?
或者...至少内存效率更高,不会花费更多的 CPU 时间来设置和迭代?
我曾考虑过使用 char
数组,然后对每个字符进行位屏蔽以访问各个位。但我不知道是否有更简单的方法,或者这是否会占用更多的 CPU 时间。
I have some code I have in the Arduino environment that requires x (in increments of 8) boolean values that are manipulatable during run time for some shift register code. So currently I am using a boolean array like so:
#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
But I was running out of RAM around 200 (1600 booleans) and didn't know why until I saw that, even though booleans are 1 bit, they are stored in 8 bits of data.
As I said before, the number of bools needed is always in an increment of 8, so I don't know if that could work to my advantage.
Is there a more memory efficient way to store 1000+ boolean values and still be able to reference them by index?
Or... At least more memory efficient that will not cost significantly more CPU time to set and iterate through?
I had thought about a char
array, and then bit masking each char to access the individual bits. But I didn't know if there was an easier way, or if this would take up considerably more CPU time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您可以轻松地使用掩码来解决这个问题。
每个字节(无符号字符)将包含 8 个布尔值,要获得第 i 个值,您只需使用
values & 即可。 (1 << i)
在 if 测试中,它会起作用,因为如果设置了正确的位,则结果将 != 为 0。要设置一个位,只需将其和或移动到值:
值 | (1 << i)
(如果未设置,则必须将其与 0 进行 AND 运算)。另一个解决方案可能是使用打包结构:
这应该管理可直接访问布尔值的元素,并允许您定义一个联合来将它们管理为 8 个单位布尔值或字节。
Yes, you could easily use masking to get around that issue..
Every byte (unsigned char) will contain 8 boolean values, to get the i-th you can just use
values & (1 << i)
in if tests, and it will work since if the correct bit is set, then result will be != to 0.To set instead a bit just shift it and or to the value:
values | (1 << i)
(in case of unset you have to AND it with 0).Another solution could be to use a packed struct:
This should manage elements with direct access to the boolean value and allow you to define an union to manage them either as 8 single bit booleans value either as bytes.
您可以具有内存效率,也可以具有计算效率,但不能同时拥有两者。
将布尔值打包到
unsigned char
数组中意味着对于任何随机读取访问,您必须:将它们存储在单独的数组元素中将其简化为:
选择其中之一取决于您的存储和性能需求如何相互平衡、您打算如何使用数据以及您愿意做出哪些权衡。就您的情况而言,直接访问方法的存储成本增加了八倍,这会耗尽内存并导致故障,因此不予考虑。这使得打包比特需要一些额外的处理。
如果您花费大量时间迭代全部或部分集合,则可以使用打包方法,并通过仅在需要时检索字节并在每次执行时执行一次移位和掩码来减少一些计算。下一点。 立即执行此操作将是过早的优化,因此只需将其放在后袋中,直到您发现访问实际上导致了瓶颈。首先让您的程序运行可用内存。
另请记住,Arduino 中使用的微控制器并不是特别复杂,并且没有大型寄存器,因此请打包到更大的寄存器中,例如
unsigned int
或unsigned long
最终可能会产生反效果。You can have memory-efficient or you can have compute-efficient, but you can't have both at the same time.
Packing booleans into an array of
unsigned char
means that for any random read access, you have to:Storing them in individual array elements cuts it down to:
Selecting one over the other depends on how your storage and performance needs balance each other, how you intend to use the data and what trade-offs you're willing to make. In your case, the directly-accessed approach costs an eight-fold increase in storage that runs you out of memory and causes a failure, so it's off the table. That leaves packed bits at a cost of some extra processing.
If you spend a lot of time iterating over all or part of the set, you can use the packed approach and cut back on some of the computation by retrieving bytes only when you need them and doing a single shift and mask each time you go after the next bit. Doing this immediately would be premature optmization, so just keep it in your back pocket until you discover that access is actually actually causing a bottleneck. Get your program to run the available memory first.
Also keep in mind that the microcontroller used in Arduino is not particularly sophisticated and doesn't have large registers, so packing into anything larger like
unsigned int
orunsigned long
might end up being couterproductive.