gpt4 book ai didi

c++ - 使用For循环生成随机视觉噪声

转载 作者:行者123 更新时间:2023-11-28 05:03:23 25 4
gpt4 key购买 nike

我开始使用arduinos之类的语言开始进入C的中等深度,并且只想提供一些有关如何使用For循环生成随机噪声的建议。
重要的一点:

void testdrawnoise() {  
int j = 0;
for (uint8_t i=0; i<display.width(); i++) {
if (i == display.width()-1) {
j++;
i=0;
}
M = random(0, 2); // Random 0/1
display.drawPixel(i, j, M); // (Width, Height, Pixel on/off)
display.refresh();
}
}


该功能在屏幕上一个接一个地绘制像素,一旦 i达到 display.width()-1,则向下移动到下一行。像素是亮(黑)还是灭(白)由 M确定。

该代码运行良好,但我认为它可以做得更好,或者至少更整洁,并且也许更有效。

输入和批评非常赞赏。

最佳答案

首先,循环永远不会结束,并且继续不断地递增j,因此,在填满屏幕一次之后,您将继续在屏幕高度之外进行循环。尽管您的库does bounds checking,在j溢出并恢复为零之前,在没有实际做有用工作的情况下肯定不会有效地使用CPU来继续循环。

另外,有符号的溢出在C ++中是未定义的行为,因此从技术上讲,您的立场是不稳定的(我本来以为Arduino总是使用-fwrapv进行编译,从而保证了有符号整数溢出(aa)的折回)。

鉴于您正在使用的库将整个帧缓冲区保留在内存中并通过refresh调用将其全部发送,因此在每个像素处重新发送它没有多大意义-尤其是因为帧传输可能是通过这是该循环中最慢的部分。因此,您可以将其移出循环。

将它们放在一起(加上缓存宽度和高度,并使用更简单的random重载),可以将其更改为:

void testdrawnoise() {
int w = display.width(), h = display.height();
for (int j=0; j<h; ++j) {
for (int i=0; i<w; ++i) {
display.drawPixel(i, j, random(2));
}
}
display.refresh();
}


(如果您的屏幕尺寸在AVR Arduino上小于256,则可以通过将所有 int更改为 byte来获得一些好处,但是请不要相信我)

请注意,这只会执行一次,您可以将其放入 loop()函数或无限循环以使其继续生成随机模式。



您可以使用提供的界面来完成此操作。现在,进入无证件领域,我们可以更快。

如上所述,您正在使用的库将整个帧缓冲区保存在内存中,按预期以每字节8位打包(按预期)在单个名为 but apparently I was mistaken且初始化为 sharpmem_buffer的全局变量中。

还应注意的是,当您在代码中要求一个随机位时,PRNG会生成一个完整的31位随机数,并且仅占用低位。为什么要浪费所有其他完美的随机位?

同时,当您调用 malloc时,库将对内存中的相应字节执行一系列布尔运算,以仅设置您要的位,而不会触及其余位。相当愚蠢,因为无论如何您都会随机覆盖其他对象。

因此,将这两个事实放在一起,我们可以执行以下操作:

void testdrawnoise() {
// access the buffer defined in another .cpp
extern byte *sharpmem_buffer;
byte *ptr = sharpmem_buffer; // pointer to current position
// end position
byte *end = ptr + display.width()*display.height()/8;
for (; ptr!=end; ++ptr) {
// store a full byte of random
*ptr = random(256);
}
display.refresh();
}


减去 drawPixel时间,它应该比以前的版本至少快8倍(我实际上期望的要多得多,因为不仅循环的核心执行了1/8的迭代,而且它也更简单-除了 refresh()之外,没有函数调用,没有分支,没有对内存的布尔操作)。

在AVR Arduino上,唯一可以进一步优化的地方可能是RNG-我们仍然只使用31位中的8位(如果它们实际上是31位?Arduino文档照常糟透了,无法提供有用的技术信息)RNG,因此我们可能会从单个RNG调用中生成3个字节的随机数,如果切换到不打扰符号位的手摇式LCG,则可能会生成4个字节。在最后一种情况下,在ARM Arduino上,我们甚至可以通过在内存中执行完整的32位存储而不是写入单个字节来获得收益。

但是,这些进一步的优化是(1)编写乏味的(如果您必须处理像素数不是24/32的倍数的屏幕),并且(2)考虑到大部分时间都将花费不大通过SPI传输。无论如何都值得一提,因为它们在没有传输瓶颈来减慢所有速度的其他情况下可能很有用。

鉴于OP的MCU实际上是Cortex M0(因此是32位ARM),因此值得尝试使用完整的32位PRNG和32位存储来使其更快。

如上所述,内置的 random返回一个带符号的值,还不清楚它提供的范围是什么。因此,我们必须推出自己的PRNG,以保证提供32个完整的随机位。

一个能提供32个随机位且状态最小的PRNG是 with a random of the obvious size;我们将直接使用来自Wikipedia的xorshift32,因为我们实际上并不需要改进的“ *”或“ +”版本(我们也不关心较大的同行提供更长的期限)。

struct XorShift32 {
uint32_t state = 0x12345678;
uint32_t next() {
uint32_t x = state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
state = x;
return x;
}
};

XorShift32 xorShift;


现在我们可以重写 testdrawnoise()

void testdrawnoise() {
int size = display.width()*display.height();
// access the buffer defined in another .cpp
extern byte *sharpmem_buffer;
/*
we can access the framebuffer as if it was an array of 32-bit words;
this is fine, since it was alloc-ed with malloc, which guarantees memory
aligned for the most restrictive built-in type, and the library only
uses it with byte pointers, so there should be no strict aliasing problem
*/
uint32_t *ptr = (uint32_t *)sharpmem_buffer;
/*
notice that the division is an integer division, which truncates; so, we
are filling the framebuffer up the the last multiple of 4 bytes; with
"strange" sizes we may be leaving out up to 3 bytes (see later)
*/
uint32_t *end = ptr + size/32;
for (; ptr!=end; ++ptr) {
// store a full byte of random
*ptr = xorShift.next();
}
// now to fill the possibly missing last three bytes
// pick it up where we left it
byte *final_ptr = (byte *)end;
byte *final_end = sharpmem_buffer + size/8;
// generate 32 random bits; it's ok, we'll need at most 24
uint32_t r = xorShift.next();
for(; final_ptr!=final_end; ++final_ptr) {
// take the lower 8 bits
*final_ptr = r;
// throw away the bits we used, get in the upper ones
r = r>>8;
}
display.refresh();
}

关于c++ - 使用For循环生成随机视觉噪声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45391453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com