Optimization 优化随机存取双线性抽样
我在做一个老式的“图像扭曲”过滤器。基本上,我有一个2D像素数组(暂时忽略它们是否为颜色、灰度、浮点、RGBA等问题)和另一个2D向量数组(带有浮点组件),图像至少与向量数组一样大。在伪代码中,我要执行以下操作:Optimization 优化随机存取双线性抽样,optimization,graphics,Optimization,Graphics,我在做一个老式的“图像扭曲”过滤器。基本上,我有一个2D像素数组(暂时忽略它们是否为颜色、灰度、浮点、RGBA等问题)和另一个2D向量数组(带有浮点组件),图像至少与向量数组一样大。在伪代码中,我要执行以下操作: FOR EACH PIXEL (x,y) vec = vectors[x,y] // Get vector val = get(img, x + vec.x, y + vec.y) // Get input at <x,
FOR EACH PIXEL (x,y)
vec = vectors[x,y] // Get vector
val = get(img, x + vec.x, y + vec.y) // Get input at <x,y> + vec
output[x,y] = val // Write to output
而lerp()
只是
FUNCTION lerp(a,b,x)
RETURN (1-x)*a + x*b
假设事先既不知道输入图像也不知道向量数组,那么什么样的高级优化是可能的?(注意:“使用GPU”是欺骗。)我能想到的一件事是在get()
中重新安排插值数学,以便我们可以缓存给定(ix,iy)的像素读取和中间计算。这样,如果连续访问同一个亚像素四边形,我们可以避免一些工作。如果向量数组是预先知道的,那么我们可以重新排列它,以便传递给get()
的坐标更为局部。这可能也有助于缓存的局部性,但代价是写入输出的内容到处都是。但是,我们不能做一些奇特的事情,比如动态缩放向量,甚至不能将扭曲效果从其原始的预先计算位置移动
唯一的另一种可能性是使用定点向量分量,可能只有非常有限的分数部分。例如,如果向量只有2位分数分量,那么只有16个子像素区域可以访问。我们可以预先计算这些参数的权重,完全避免很多插值运算,但要保证质量
还有其他想法吗?在实现它们之前,我想积累一些不同的方法,看看哪一种是最好的。如果有人能告诉我一个快速实现的源代码,那就太好了。有趣的问题
您的问题定义基本上强制了对[x,y]中的不可预测的访问,因为可能会提供任何向量。假设向量图像倾向于引用局部像素,第一个优化将是确保以适当的顺序遍历内存,以充分利用缓存局部性。这可能意味着在“每个像素”循环中扫描32*32块,以便在短时间内尽可能多地在[x,y]中点击相同的像素
最有可能的是,算法的性能将受到两个因素的限制
从主存加载向量[x,y]
和[x,y]的速度有多快
af = (1 - xf) * ( 1 - yf )
bf = ( xf) * ( 1 - yf )
cf = (1 - xf) * ( yf )
df = ( xf) * ( yf )
然后计算
a *= af
b *= bf
c *= cf
d *= cf
return (a + b + c + d)
这两个步骤很有可能都可以通过少量的SSE指令(取决于像素表示)来完成
我认为缓存中间值不太可能有用-向量请求中超过1%的向量不太可能指向完全相同的位置,缓存内容将花费比节省更多的内存带宽
如果在处理向量[x,y]
时,使用cpu上的预取指令在[vectors[x+1,y]]中预取,可能会提高内存性能,否则cpu将无法预测内存的随机漫游
提高算法性能的最后一种方法是一次处理输入像素块,即x[0..4],x[5..8]
-这可以展开内部数学循环。但是,您很可能内存不足,因此这不会有任何帮助
a *= af
b *= bf
c *= cf
d *= cf
return (a + b + c + d)