* native code compiler and exceptions
@ 1996-09-27 11:21 Jocelyn Serot
1996-09-27 11:41 ` Pierre Weis
0 siblings, 1 reply; 7+ messages in thread
From: Jocelyn Serot @ 1996-09-27 11:21 UTC (permalink / raw)
To: caml-list
Hello there,
I wanted to ask the ocaml implementors the following question:
Is there a deep, "fundamental", reason why certain exceptions (in particular
those raised by array accesses out of bound) are not handled in same way
by the bytecode compiler and the native compiler, or is it a temporary
weakness that will be removed in future releases ?..
Here's - in short ;-) - why i am wondering about that:
I've written an image processing module in ocaml. Some functions in this
module (for example, convolutions, ...) relies heavily on bound-violation
exceptions for handling clipping effect at image boundaries. Well, now every-
things works fine under the bytecode compiler. But i'd like to take advantage
of teh native code compiler to boost all that code a bit...
Thanks for any clue
Jocelyn
--
E-mail: Jocelyn.Serot@lasmea.univ-bpclermont.fr .............................
S-mail: LASMEA - URA 1793 CNRS, Universite Blaise Pascal, 63177 Aubiere cedex
Tel: (33) 73.40.73.30 - Fax: (33) 73.40.72.62 ...............................
.... http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Welcome.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: native code compiler and exceptions
1996-09-27 11:21 native code compiler and exceptions Jocelyn Serot
@ 1996-09-27 11:41 ` Pierre Weis
0 siblings, 0 replies; 7+ messages in thread
From: Pierre Weis @ 1996-09-27 11:41 UTC (permalink / raw)
To: Jocelyn Serot; +Cc: caml-list
Hello,
> Is there a deep, "fundamental", reason why certain exceptions (in particular
> those raised by array accesses out of bound) are not handled in same way
> by the bytecode compiler and the native compiler, or is it a temporary
[...]
> I've written an image processing module in ocaml. Some functions in this
> module (for example, convolutions, ...) relies heavily on bound-violation
> exceptions for handling clipping effect at image boundaries.
Wao! To ``rely heavily on array bounds violation'' is a very ugly style
of programming. I could not imagine why you need to use this style. I
would suggest that you just avoid these violations : this would rend
your program clearer and fully compatible with the optimizing
compiler. Then, you should gain the full benefit of a native code
compilation. Moreover, if your code is really array bound clear, you
could use the unsafe option of the compiler, that remove every array
bound test. (Waiting for an automatic array bound check removing pass
in the optimizing compiler...)
Pierre Weis
INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: native code compiler and exceptions
@ 1996-09-27 12:46 Jocelyn Serot
1996-09-27 15:58 ` Pierre Weis
0 siblings, 1 reply; 7+ messages in thread
From: Jocelyn Serot @ 1996-09-27 12:46 UTC (permalink / raw)
To: caml-list
In his answer to my original question, P. Weis (Pierre.Weis@inria.fr) says:
> Wao! To ``rely heavily on array bounds violation'' is a very ugly style
> of programming. I could not imagine why you need to use this style.
Well, maybe the formulation ``rely heavily on array bounds violation'' was
a bit misleading. My code relies on the correct handling of exceptions that,
at the lowest level may be trapped as array bound violation.
I will try yo explain my pb on a small example.
Suppose that images are represented as pixel 2d-arrays (in fact, images
are implemented as ADTs, with their internal representation hidden).
# type image = int array array
# let get_pixel i y x = i.(y).(x)
# let set_pixel i y x p = i.(y).(x) <- p
# let create nr nc = Array.new_matrix nr nc 0
What i want to do is to compute, for example is a simple 2d-convolution,
turning pixel(x,y) into (p(x-1,y)+p(x,y-1)+p(x+1,y)+p(x,y+1))/4.
A possible manner to handle the clipping effect at image boundaries is to
set that p(x,y) = 0 whenever x<0 ot y<0.
So it does not seem to me so "ugly" to write my convolution fn like that:
# let conv im =
# let nr = nb_rows im and nc = nb_cols im in
# let im' = create nr nc in
# for y = 0 to pred nr do for x = 0 to pred nc do
# let p1 = try_get_pixel im (x-1) y 0 in
# let p2 = try_get_pixel im x (y-1) 0 in
# let p3 = try_get_pixel im (x+1) y 0 in
# let p4 = try_get_pixel im x (y+1) 0 in
# set_pixel im' (y,x) ((p1+p2+p3+p4)/4) done done;
# m'
making use of the given access fn:
# let try_get_pixel im y x clip =
# try get_pixel im y x with Invalid_argument _ -> clip
(btw, note that is this case clip might be a _fn_ of the "faulty" coordinates,
like:
# let try_get_pixel im y x clip =
# try get_pixel im y x with Invalid_argument _ -> clip y x
)
Is this not "good" fnal programming style ?..
Or does the "ugliness" lies only in the [... with Invalid_argument _ ->...]
construct ? In this case, i guess i should test _explicitely_ whether (y,x) are
in bounds instead of relying of the exception [Invalid_argument "Array.get"].Ie:
# let try_get_pixel im y x clip =
# if (y<0 || y>=(nb_rows im) || x<0 || x>=(nb_cols im)) then clip
# else get_pixel im y x
Is it what you mean ?
Jocelyn
--
E-mail: Jocelyn.Serot@lasmea.univ-bpclermont.fr .............................
S-mail: LASMEA - URA 1793 CNRS, Universite Blaise Pascal, 63177 Aubiere cedex
Tel: (33) 73.40.73.30 - Fax: (33) 73.40.72.62 ...............................
.... http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Welcome.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: native code compiler and exceptions
1996-09-27 12:46 Jocelyn Serot
@ 1996-09-27 15:58 ` Pierre Weis
0 siblings, 0 replies; 7+ messages in thread
From: Pierre Weis @ 1996-09-27 15:58 UTC (permalink / raw)
To: Jocelyn Serot; +Cc: caml-list
Hi,
> I will try yo explain my pb on a small example.
> Suppose that images are represented as pixel 2d-arrays (in fact, images
> are implemented as ADTs, with their internal representation hidden).
>
> # type image = int array array
> # let get_pixel i y x = i.(y).(x)
> # let set_pixel i y x p = i.(y).(x) <- p
> # let create nr nc = Array.new_matrix nr nc 0
>
> What i want to do is to compute, for example is a simple 2d-convolution,
> turning pixel(x,y) into (p(x-1,y)+p(x,y-1)+p(x+1,y)+p(x,y+1))/4.
Well, the set and get functions are well suited for the image
abstraction, but if efficiency is a problem, you should not use these
functions to implement low level functions on images:
get_pixel i y x is much more time consuming than its inlined counterpart
i.(y).(x). For efficiency reasons, the last version should be prefered
when available, for instance from within the abstraction...
> A possible manner to handle the clipping effect at image boundaries is to
> set that p(x,y) = 0 whenever x<0 ot y<0.
> So it does not seem to me so "ugly" to write my convolution fn like that:
>
> # let conv im =
> # let nr = nb_rows im and nc = nb_cols im in
> # let im' = create nr nc in
> # for y = 0 to pred nr do for x = 0 to pred nc do
> # let p1 = try_get_pixel im (x-1) y 0 in
> # let p2 = try_get_pixel im x (y-1) 0 in
> # let p3 = try_get_pixel im (x+1) y 0 in
> # let p4 = try_get_pixel im x (y+1) 0 in
> # set_pixel im' (y,x) ((p1+p2+p3+p4)/4) done done;
> # m'
>
> making use of the given access fn:
>
> # let try_get_pixel im y x clip =
> # try get_pixel im y x with Invalid_argument _ -> clip
The introduction of try_get_pixel adds another indirection level: 2
function calls and an exception handler to access one pixel! That may
10 or 100 times slowlier than the direct access.
> (btw, note that is this case clip might be a _fn_ of the "faulty" coordinates,
> like:
>
> # let try_get_pixel im y x clip =
> # try get_pixel im y x with Invalid_argument _ -> clip y x
> )
>
> Is this not "good" fnal programming style ?..
Well this is functional, since you call functions, but once more there is no
need to call a function with 2 arguments to return a constant (0 in
your case).
> Or does the "ugliness" lies only in the [... with Invalid_argument _ ->...]
> construct ? In this case, i guess i should test _explicitely_ whether (y,x) are
> in bounds instead of relying of the exception [Invalid_argument "Array.get"].Ie:
>
> # let try_get_pixel im y x clip =
> # if (y<0 || y>=(nb_rows im) || x<0 || x>=(nb_cols im)) then clip
> # else get_pixel im y x
>
> Is it what you mean ?
Yes, you're right. There is no good reasons for explicitely trapping the
Invalid_argument exception from within regular parts of your programs:
if you know that you may call a primitive with an invalid argument,
you should avoid this call, instead of trapping the error afterwards.
By the way, you may observe that the function try_get_pixel
may be simplified when called from within ``conv'': many of the tests
are statically known and may be discarded. The resulting code exhibits
the remaining tests but is still readable, while much more efficient:
let conv im =
let nr = nb_rows im and nc = nb_cols im in
let im' = create nr nc in
for y = 0 to pred nr do for x = 0 to pred nc do
let p1 = if x = 0 then 0 else im.(x - 1).(y) in
let p2 = if y = 0 then 0 else im.(x).(y - 1) in
let p3 = if x = nc - 1 then 0 else im.(x + 1).(y) in
let p4 = if y = nr - 1 then 0 else im.(x).(y + 1) in
im'.(y).(x) <- ((p1 + p2 + p3 + p4) / 4) done done;
m'
If you need an even more efficient routine, you should consider
removing the tests if x = 0, if y = 0, and so on, from inside the
loop, decomposing the loop into a straightforward loop
for y = 1 to nr - 2 do for x = 1 to nc - 2 do
with no tests at all, and complete im' with the remaining cases
afterwards ...
In any case, when efficiency is concerned, you should avoid calling 2
or 3 functions to perform an atomic task. I should say that, even if
there is no efficiency consideration, calling a function that just
calls a function that calls a function that performs an atomic task,
does not help reading the program ...
Pierre Weis
INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: native code compiler and exceptions
@ 1996-09-27 13:04 Harrison R. Ulrich (contractor)
1996-09-27 16:03 ` Christophe Raffalli
0 siblings, 1 reply; 7+ messages in thread
From: Harrison R. Ulrich (contractor) @ 1996-09-27 13:04 UTC (permalink / raw)
To: caml-list
Hi,
I must confess to be ignorant of caml and other things ...
Is caml a good language for developing GUIs?
Thanks,
Dick
^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <199609271524.RAA27638@pauillac.inria.fr>]
* Re: native code compiler and exceptions
[not found] <199609271524.RAA27638@pauillac.inria.fr>
@ 1996-09-27 16:01 ` Jocelyn Serot
0 siblings, 0 replies; 7+ messages in thread
From: Jocelyn Serot @ 1996-09-27 16:01 UTC (permalink / raw)
To: Pierre Weis; +Cc: caml-list
Thanks for your enlightments about efficiency concerns in Caml.
Seems like i have re-discovered an evidence: efficiency AND abstraction
do not live well together in the world of programs :-)
For example, i do agree with your optimisation of the conv fn:
> let conv im =
> let nr = nb_rows im and nc = nb_cols im in
> let im' = create nr nc in
> for y = 0 to pred nr do for x = 0 to pred nc do
> let p1 = if x = 0 then 0 else im.(x - 1).(y) in
> let p2 = if y = 0 then 0 else im.(x).(y - 1) in
> let p3 = if x = nc - 1 then 0 else im.(x + 1).(y) in
> let p4 = if y = nr - 1 then 0 else im.(x).(y + 1) in
> im'.(y).(x) <- ((p1 + p2 + p3 + p4) / 4) done done;
> m'
>
But in my code, conv is in fact a generalized "map" fn implemented as a higher
order fn, sth with a signature like:
# val conv : (coord -> coord array) ->
# (pixel array -> pixel) -> (coord -> pixel) -> t -> t
# (* [conv g f clp im] is [im']
# where im'@@(y,x) = f [|p1;..;pk|]
# where pi = im@@(yi,xi) ,if in_bounds m (yi,xi),
# clp (yi,xi) ,otherwise
# where [|(y1,x1);...;(yk,xk)|] = g (y,x) *)
# (*
# * [g] is the "neighboorhing fn"
# * [f] is the "combining fn"
# * [clp] is the "clipping fn" *)
This level of abstraction - that may be useful if you dont want to spend to
time writing "for" loops on image representations - clearly precludes the sort
of optimisation you suggest ...
So i am on my own now, speed or abstraction: this is the question ;-)
Thanks for your help,
Jocelyn
--
E-mail: Jocelyn.Serot@lasmea.univ-bpclermont.fr .............................
S-mail: LASMEA - URA 1793 CNRS, Universite Blaise Pascal, 63177 Aubiere cedex
Tel: (33) 73.40.73.30 - Fax: (33) 73.40.72.62 ...............................
.... http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Welcome.html
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~1996-09-27 16:09 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-09-27 11:21 native code compiler and exceptions Jocelyn Serot
1996-09-27 11:41 ` Pierre Weis
1996-09-27 12:46 Jocelyn Serot
1996-09-27 15:58 ` Pierre Weis
1996-09-27 13:04 Harrison R. Ulrich (contractor)
1996-09-27 16:03 ` Christophe Raffalli
[not found] <199609271524.RAA27638@pauillac.inria.fr>
1996-09-27 16:01 ` Jocelyn Serot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).