lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 17 February 2011 00:14, Miles Bader <miles@gnu.org> wrote:
> Alexander Gladysh <agladysh@gmail.com> writes:
>>>> Rule #437: Never hoist out constants (if possible)!
>>
>>>> Always write constants inline, otherwise they are treated as
>>>> variables, which generates worse code. And, yes, even plain Lua is
>>>> able to fold 1/5 into a constant. It's important to write these
>>>> unambiguously -- FP arithmetic is not associative!
>>
>>> Good to know, but bad programming practice from a formal point of view. :-)
>>> I always recommend to beginners in programming to replace magic numbers with
>>> constants, for readability and consistency. I understand that speed
>>> optimizations sometime have to break these nice rules (like manual loop
>>> unrolling and such).
>>
>> My opinion as well.
>
> And mine.
>
> If Luajit has trouble identifying these, perhaps it would be useful to
> have some sort of annotation that could be added to tell it?
>
> E.g., in comments or something... (so the code would still be valid Lua code)

It is astonishing how a whole sub-thread developed about adding
constants to Lua and no one even bothered to check if and how much of
difference it would make.  I did.  Following Mike's advice I inlined
all these constants in ode45.lua posted earlier (attached) and added a
big loop at the end, so it runs for a bit.  The result:

  original:  0.88sec
  inlined:   1.35sec

So it looks like Mike was wrong---at least in this instance inlining
results in a slower code than before.  (Not what I would expect
either, but there you go.  Can't argue with the numbers.)  But the
difference is not nearly as dramatic as in Francesco's "small loops"
example (a factor of ~1.5 vs. over 20).

Mike, could you comment on this?  I hope you are not tired of this
thread yet.  I think that the "small loops" case might be quite
important for Lua.  In an array based language like MATLAB one can
just write:

  vec3 = vec1 + vec2

to add together two arrays and the good elves take care of the rest,
but in Lua we have to write loops.  Is code
templating/specialization/manual unrolling the only way to address
that in luajit?  Wouldn't it be possible to do something like in the
example I posted earlier?

Cheers,

Tomek




local function ode_dormandprince ( fxy , x0 , x1 , y0 , tol , hmax , hmin , maxiter )
	local x = x0
	local y = y0
	local h = hmax

	local i = 1
	while true do
		local K1 = fxy ( x , y )
		local K2 = fxy ( x + (1.0 / 5)*h, y + h*( (1/5)*K1 ) )
		local K3 = fxy ( x + (3.0 / 10)*h, y + h*( (3/40)*K1 + (9/40)*K2 ) )
		local K4 = fxy ( x + (4.0 / 5)*h, y + h*( (44/45)*K1 + (-56/15)*K2 + (32/9)*K3 ) )
		local K5 = fxy ( x + (8.0 / 9)*h, y + h*( (19372/6561)*K1 + (-25360/2187)*K2 + (64448/6561)*K3 + (-212/729)*K4 ) )
		local K6 = fxy ( x + h, y + h*( (9017/3168)*K1 + (-355/33)*K2 + (46732/5247)*K3 + (49/176)*K4 + (-5103/18656)*K5 ) )
		local K7 = fxy ( x + h, y + h*( (35/384)*K1 + (0)*K2 + (500/1113)*K3 + (125/192)*K4 + (-2187/6784)*K5 + (11/84)*K6 ) )

		local err = math.abs ( K1*((35/384)-(5179/57600)) + K3*((500/1113)-(7571/16695)) + K4*((125/192)-(393/640)) + K5*((-2187/6784)-(-92097/339200)) + K6*((11/84)-(187/2100)) + K7*((0)-(1/40)) )
		if err < tol then
			x = x + h
			y = y + h * ((35/384)*K1+(500/1113)*K3+(125/192)*K4+(-2187/6784)*K5+(11/84)*K6)
		end

		local delta = 0.84 * (tol/err)^(1/5)
		if delta <= 0.1 then
			h = h * 0.1
		elseif delta >= 4 then
			h = h * 4.0
		else
			h = delta * h
		end

		if h > hmax then
			h = hmax
		end

		if x >= x1 then
			return y , nil , i
		elseif x + h > x1 then
			h = x1 - x
		elseif h < hmin then
			return false , y , i -- hmin exceeded
		end

		i = i + 1
		if i >= maxiter then
			return false , y , i -- maxiter reached
		end
	end
end

for i = 1,1e5 do
  ode_dormandprince( function(x,y) return x+y end , 0 , 1 , 1.24 , 1e-5 , 1 , 0.01 , 1000 )
end
print(ode_dormandprince ( function(x,y) return x+y end , 0 , 1 , 1.24 , 1e-5 , 1 , 0.01 , 1000 ))