这是在社区大学。我失败了,但想知道答案。
问题在于:您有一个表示图像的2D结构数组。每个结构都有一个红色,绿色,蓝色和alpha值。可以有更多信息,但不是解决问题所必需的。
假设图像是4000x4000或1600万个元素。每个角落都需要更新/检查每个元素。
对于您需要的每个元素:
“你不能强迫这一点,以更聪明的方式思考;你需要一个更好的算法”
我基本上做了一个循环。我是最快的,但他说这是“关于找到一个更好的算法,而不是使用可爱的编译器和指针技巧”。
还需要在纯C中。没有OpenMP / Threads或OpenGL着色,OpenCL等......只有带有标准库的ANSI C(甚至禁止使用GNU / POSIX库)。
我问过按位操作,他说“那些在C [??]中非常昂贵,而且是关于编写一个快速而可靠的算法,而不是你一直想出的这些可爱的技巧”。
所有提示?
答案 0 :(得分:6)
是的,让我们都弄清楚如何写一个算法“以'有趣'的方式修改蓝色。”,只要它“快速而坚实”。很高兴的社区学院教学如此强大。我从来没有听说过按位操作很贵。比较贵的什么?当你说你是“最快的”时,你的意思是你是第一个提出答案的人,或者你的答案是最有效的实施方式吗?如果你被迫将数据存储为结构的2D数组(而不是树),我不确定你还能做些什么。所以你知道你失败了,但没有被告知正确的答案?现在这就是我所说的edjumacation!
答案 1 :(得分:5)
rand()
调用很可能会主宰程序的运行时,因此尝试使用智能循环结构或花哨的按位操作时,没有任何意义。
因此,最有效的优化可能实际上是将每个值从rand拆分为字节(取决于rand实现),以减少调用。
至于老师真正想要的是什么,这是一个疯狂的猜测:
答案 2 :(得分:4)
更新大型阵列最重要的一点是利用局部性来利用memory hierarchy。这会隐藏内存延迟,从而加速您的算法。
首先,您希望将每个像素的颜色一起处理,因为它们位于相同的结构中。像素的处理完全适合现代CPU的寄存器组。根据实际的存储情况,这里可以进行一些比特/字节/字的调整,但听起来你的教练并没有强调这一点。
其次,您希望按照存储在内存中的顺序更新像素。这意味着循环内部循环中的内部数组维度。这使编译器和CPU能够以大块(关键字缓存行和预取)有效地访问像素。
完全不同的方法是添加一个间接层。
不是直接访问图像阵列,而是通过访问器函数路由所有访问。现在,您可以编写访问器函数来实现对图像所需的更改,而无需访问数组,甚至可以遍历所有像素!
这就像面向对象语言中的Decorator模式。
答案 3 :(得分:2)
这看起来像是面试问题。真傻!如果你必须访问每个像素,那么你必须使用循环!毕竟,这是他们的目的。你可以做的最好的事情是做一个循环而不是两个循环,并在每次迭代时编辑更多的像素
答案 4 :(得分:2)
'每一个回合'
所以也许有一些优化在第一次迭代后不执行红色检查,因为这些值将是静态的
答案 5 :(得分:0)
我能想到的唯一方法是“假设图像是4000x4000或1600万个元素。每个元素需要每一轮都要更新/检查。”实际上意味着“假设图像是4000x4000或1600万个元素。每个元素需要每一轮都要更新/检查。”
然后,它说“还需要在纯C中。没有OpenMP / Threads或OpenGL着色,OpenCL等......”为什么要提到这个基本问题的“OpenGL着色”?
我认为(我只是猜测)实际问题有更多细节,并且正在推动学生以某种方式剪切图像处理(即图像的某些部分被覆盖或屏幕外,所以你可以跳过这些位)。
这只是猜测。因为我的小弟弟会说“这没有意义,否则!!!”
答案 6 :(得分:0)
也许教练正在寻找通过在单独的循环中处理颜色而获得的一些性能:
for each pixel
red pixel = (red pixel < 50) ? 50 : ((red pixel > 250) ? 250 : red pixel);
end-for
for each pixel
green pixel = 256 * rand()
end-for
for each pixel
blue pixel = (green pixel * 1024) % 256;
end-for
可能有更好的表现,但只有剖析才能说明。
此方法的一个优点是每种颜色都可以由独立的线程或核心处理。