我目前正在調查數組求和的穩健方法,並實施了Shewchuk在"Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"中發佈的算法。雖然實施的算法按照預期在gfortran
中工作,但ifort
優化了對策。優化失敗魯棒性措施
給予一定的情況下,這裏是我的代碼:
module test_mod
contains
function shewchukSum(array) result(res)
implicit none
real,intent(in) :: array(:)
real :: res
integer :: xIdx, yIdx, i, nPartials
real :: partials(100), hi, lo, x, y
nPartials = 0
do xIdx=1,size(array)
i = 0
x = array(xIdx)
! Calculate the partial sums
do yIdx=1,nPartials
y = partials(yIdx)
hi = x + y
if (abs(x) < abs(y)) then
lo = x - (hi - y)
else
lo = y - (hi - x)
endif
x = hi
! If a round-off error occured, store it. Exact comparison intended
if (lo == 0.) cycle
i = i + 1 ; partials(i) = lo
enddo ! yIdx
nPartials = i + 1 ; partials(nPartials) = x
enddo ! xIdx
res = sum(partials(:nPartials))
end function
end module
和主叫測試程序
program test
use test_mod
implicit none
print *, sum([1.e0, 1.e16, 1.e0, -1.e16])
print *,shewchukSum([1.e0, 1.e16, 1.e0, -1.e16])
end program
使用gfortran
與產生正確的結果爲所有優化級別編譯:
./a.out
0.00000000
2.00000000
ifort
然而,產生零上述-O0
所有優化:
./a.out
0.00000000
0.00000000
我試着調試代碼,並就下到裝配水平,想通了,ifort
被優化掉的lo
計算和if (lo == 0.) cycle
後的操作。
是否有可能強制ifort
執行所有級別的優化的完整操作?這個添加是計算的關鍵部分,我希望它儘可能快地運行。 爲了比較,gfortran
在-O2
執行該代碼大約比ifort
在-O0
(對於長度> 100k的陣列測量)快8-10倍。
如果有其他編譯選項,您是否使用ifort? – francescalus
@francescalus對於此測試,沒有其他選項。用於調試'-warn all -check',用於檢查彙編代碼'-S -fcode-asm -fsource-asm'。 –
可能有一些來自整個網站,所以你可以看看'-dryrun'的輸出,尤其是你是否有'-assume noprotect_parens'? [如果我使用'-assume protect_parens',我會得到您期望的答案 - 但也可能會有其他事情發生。]儘管這是默認設置,因此可能不會列出。 – francescalus