Consider these four function in different form:
f1[ls1_] := Append[Rest@ls1, 0.] + Prepend[Most@ls1, 0.]
f2 = Compile[{{ls1, _Real, 1}},
Append[Rest@ls1, 0.] + Prepend[Most@ls1, 0.],
CompilationTarget -> "C"];
f3[ls_] := Module[{n = Length@ls, tp = ls},
tp[[1]] = ls[[2]];
tp[[n]] = ls[[n - 1]];
Do[
tp[[i]] = ls[[i - 1]] + ls[[i + 1]], {i, 2, n - 1}
];
tp]
f4 = Compile[{{ls, _Real, 1}},
Module[{n = Length@ls, tp = ls},
tp[[1]] = ls[[2]];
tp[[n]] = ls[[n - 1]];
Do[
tp[[i]] = ls[[i - 1]] + ls[[i + 1]], {i, 2, n - 1}
];
tp], CompilationTarget -> "C"
];
Comparing their performance, we can see that the functional version f1 and f2 have about the same performance, but the compiled procedural version f4 is about 2X slower.
ls = Sin /@ (Range[1, 2000]/2000.);
AbsoluteTiming[TimeConstrained[Do[f1[ls];, {20000}], 5]]
AbsoluteTiming[TimeConstrained[Do[f2[ls];, {20000}], 5]]
AbsoluteTiming[TimeConstrained[Do[f3[ls];, {20000}], 5]]
AbsoluteTiming[TimeConstrained[Do[f4[ls];, {20000}], 5]]
(*{0.976474,Null}*)
(*{0.784508,Null}*)
(*{5.000856,$Aborted}*)
(*{1.595374,Null}*)
However, if we test the procedural version in Fortran (code at the end), it runs about 4X faster than f2.
xslittlegrass$ ifort -r8 -O0 test.f90
xslittlegrass$ ./a.out
0.232574000000000
xslittlegrass$
Questions:
- Why
f4is about 2X slower thanf1andf2? - Why
f4is about 7X slower than the Fortran version? - Can we make a compiled version that has comparable performance to the Fortran version?
- I thought that a procedural function compiled to C is comparable in performance compared to procedural functions written in C. But this example seems to disagree with it. So in general how large is the gap of the performance between these two?
test.f90
program main
implicit none
integer,parameter :: N0 = 2000
integer i,j
real(kind=8) :: list(N0), result(N0),start,finish
do i = 1, N0
list(i) = sin(i/real(N0))
end do
call CPU_TIME(start)
do j = 1, 20000
result(1) = list(2)
result(N0) = list(N0-1)
do i=2,N0-1
result(i) = list(i+1) + list(i-1)
end do
end do
call CPU_TIME(finish)
write(*,*) finish-start
end program
CompilePrintoutput for those compiled functions? Maybe something in the way they are translated to compiled code might explain the difference. Also Leonid has a good set of pointers on How to compile effectively. – MarcoB Jul 22 '15 at 21:49InsetandDrop. – dr.blochwave Jul 22 '15 at 22:02