轻松的脑力劳动,更好的算法

时间:2011-04-22 16:38:28

标签: c algorithm

这是在社区大学。我失败了,但想知道答案。

问题在于:您有一个表示图像的2D结构数组。每个结构都有一个红色,绿色,蓝色和alpha值。可以有更多信息,但不是解决问题所必需的。

假设图像是4000x4000或1600万个元素。每个角落都需要更新/检查每个元素。

对于您需要的每个元素:

  • 如果<
  • 将红色字节设置为50 50或设定为205> 205
  • 使用rand()
  • 将绿色字节设置为0到255之间的随机值
  • 以“有趣”的方式修改蓝色。

“你不能强迫这一点,以更聪明的方式思考;你需要一个更好的算法”

我基本上做了一个循环。我是最快的,但他说这是“关于找到一个更好的算法,而不是使用可爱的编译器和指针技巧”。

还需要在纯C中。没有OpenMP / Threads或OpenGL着色,OpenCL等......只有带有标准库的ANSI C(甚至禁止使用GNU / POSIX库)。

我问过按位操作,他说“那些在C [??]中非常昂贵,而且是关于编写一个快速而可靠的算法,而不是你一直想出的这些可爱的技巧”。

所有提示?

7 个答案:

答案 0 :(得分:6)

是的,让我们都弄清楚如何写一个算法“以'有趣'的方式修改蓝色。”,只要它“快速而坚实”。很高兴的社区学院教学如此强大。我从来没有听说过按位操作很贵。比较贵的什么?当你说你是“最快的”时,你的意思是你是第一个提出答案的人,或者你的答案是最有效的实施方式吗?如果你被迫将数据存储为结构的2D数组(而不是树),我不确定你还能做些什么。所以你知道你失败了,但没有被告知正确的答案?现在这就是我所说的edjumacation!

答案 1 :(得分:5)

rand()调用很可能会主宰程序的运行时,因此尝试使用智能循环结构或花哨的按位操作时,没有任何意义。

因此,最有效的优化可能实际上是将每个值从rand拆分为字节(取决于rand实现),以减少调用。


至于老师真正想要的是什么,这是一个疯狂的猜测:

  1. 使用rand设置绿色字节
  2. 使用一些奇特的方法设置红色字节
  3. 在您喜欢的方法中的某处包含蓝色字节,因此它会获得一个新值作为方便的副作用
  4. 结束了一个神秘而毫无意义的单行(因为他认为程序越少,行必须越快)

答案 2 :(得分:4)

解决方案1 ​​

更新大型阵列最重要的一点是利用局部性来利用memory hierarchy。这会隐藏内存延迟,从而加速您的算法。

首先,您希望将每个像素的颜色一起处理,因为它们位于相同的结构中。像素的处理完全适合现代CPU的寄存器组。根据实际的存储情况,这里可以进行一些比特/字节/字的调整,但听起来你的教练并没有强调这一点。

其次,您希望按照存储在内存中的顺序更新像素。这意味着循环内部循环中的内部数组维度。这使编译器和CPU能够以大块(关键字缓存行和预取)有效地访问像素。

解决方案2

完全不同的方法是添加一个间接层。

不是直接访问图像阵列,而是通过访问器函数路由所有访问。现在,您可以编写访问器函数来实现对图像所需的更改,而无需访问数组,甚至可以遍历所有像素!

这就像面向对象语言中的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

可能有更好的表现,但只有剖析才能说明。

编辑1:

此方法的一个优点是每种颜色都可以由独立的线程或核心处理。