簡體   English   中英

優化浮點除法和轉換操​​作

[英]Optimizing a floating point division and conversion operation

我有以下公式

float mean = (r+b+g)/3/255.0f;

我想加快速度。 有以下先決條件

0<= mean <= 1  and 0 <= r,g,b <= 255 and r, g, b are unsigned chars

因此,如果我嘗試使用>> 8就像除以256的事實,我會使用類似的東西

float mean = (float)(((r+b+g)/3) >> 8);

這將始終返回0.有沒有辦法跳過昂貴的浮動分區,最終仍然是0到1之間的平均值?

將您的分區預轉換為可乘法常量:

a / 3 / 255

是相同的

a * (1 / (3 * 255))

所以預先計算:

const float AVERAGE_SCALE_FACTOR = 1.f / (3.f * 255.f)

然后就做

float mean = (r + g + b) * AVERAGE_SCALE_FACTOR;

因為乘法通常比分割快很多。

你明顯將平均值與其他東西進行比較,也就是在0和1之間。你怎么把這個東西乘以255呢?

讓我們看看真正的編譯器實際上用這個代碼做了什么? 我喜歡mingw gcc 4.3(x86)。 我用過“gcc test.c -O2 -S -c -Wall”

這個功能:

float calc_mean(unsigned char r, unsigned char g, unsigned char b)
{
    return (r+b+g)/3/255.0f;
}

生成此對象代碼(為了清楚起見,刪除了函數入口和退出代碼。我希望我添加的注釋大致正確):

movzbl 12(%ebp), %edx    ; edx = g
 movzbl 8(%ebp), %eax     ; eax = r
 addl %eax, %edx        ; edx = eax + edx
 movzbl 16(%ebp), %eax    ; eax = b
 addl %eax, %edx        ; edx = eax + edx
 movl $1431655766, %eax ; 
 imull %edx              ; edx *= a const
 flds LC0               ; put a const in the floating point reg
 pushl %edx              ; put edx on the stack
 fidivrl (%esp)            ; float reg /= top of stack

而這個功能:

float calc_mean2(unsigned char r, unsigned char g, unsigned char b)
{
    const float AVERAGE_SCALE_FACTOR = 1.f / (3.f * 255.f);
    return (r+b+g) * AVERAGE_SCALE_FACTOR;
}

生成這個:

movzbl 12(%ebp), %eax    
 movzbl 8(%ebp), %edx
 addl %edx, %eax
 movzbl 16(%ebp), %edx
 addl %edx, %eax
 flds LC2
 pushl %eax
 fimull (%esp)

如您所見,第二個功能更好。 使用-freciprocal-math進行編譯會將fidivrl從第一個函數轉換為fimull,這應該是一個改進。 但第二個功能仍然更好。

但是,如果您認為現代桌面CPU具有類似18級流水線的功能並且每個周期能夠執行其中幾條指令,您可以看到這些功能的性能將由於數據依賴性而受到停頓的支配。 希望你的程序有這個代碼片段內聯並且有一些循環展開。

考慮到隔離的這種小代碼片段並不理想。 這有點像用雙筒望遠鏡粘在眼窩上駕駛汽車。 縮小男人!

如Andrew所示,原始功能根本沒有優化。 編譯器不能,因為您首先將總和除以整數,然后除以浮點數。 這與乘以上述平均比例因子不同。 如果你將(r + g + b)/3/255.0f改為(r + g + b)/3.0f/255.0f,編譯器可能會優化它以自動使用fimull。

為平台優化此類操作是非常常見的,而不是作為算法或可移植的C. 虛擬配音博客非常值得閱讀有關如何在針對x86和x64架構的軟件中完成的提示,並且有幾個關於優化像素平均值的條目1 2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM