Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-05 Thread Sven Neumann

Hi,

[EMAIL PROTECTED] writes:

  but you continue to state that it makes the code cleaner which it
  clearly doesn't.
 
 I say using a type that represents the actual type of the value
 closely is a feature and not a bug. What wrong about seing:
 Hey, this value is supposed to be unsigned?
 This is a cleanup like using enums instead of magic values.

if we'd use a programming language that would properly support ranged
types, it'd be a cleanup. C however doesn't assure that. If the
program would throw a signed exception if a negative value is ever 
assigned to an unsigned variable, we'd indeed be able to catch bugs
and declaring variables as unsigned would make sense. Since this is
not the case, the use of unsigned variables is dangerous without 
giving any real advantages.

  it gives a small improvement and is probably a valid optimization in
  this place.
 
 That's also not the point. You doubted that using unsigneds/signeds
 doesn't make a difference and I told you that it might not make a
 difference on all platforms and compilers but definitely does in not
 so few cases.

your example involved a modulo operation. Modulo is only properly 
defined on positive values so it definitely makes sense to use an 
unsigned variable here. But then modulo operations are rare, 
subtractions are much more frequent and they will give unexpected
results if unsigned variables are involved.

  The difference to the changes I reverted is that this is a
  very local change. The function is small and the variable is local. It
  is easy to decide that using an unsigned integer here does not have
  any unwanted side effects.
 
 Sure, but since you're breaking GIMP anyways what's the problem with
 doing it correctly here? BTW: I tested the afffected functions
 (including the brushes that you stated would break) and at least there
 is no obvious breakage but if someone is careing about the code it can
 only get better not worse.

you can't have tested all possible usage patterns since there are way
too many.

  Your changes however did affect mostly headers. This means the values
  are used in a lot of places and it is almost impossible to check them
  all. Even if you would check them all, a future change to the code
  might introduce a bug because the one who did the change didn't think
  about the unsignedness of the variable (which is defined somewhere
  else).
 
 It will introduce bugs but it will also make a few older bugs obvious
 and correctable.

the point is: how are we supposed to catch them? If the compiler would
give us hints like it does for wrong usage of consts and enums, great.
However, this is not the case unfortunately.

  Since the code is very much in flux right now, a lot of these
  changes are going to happen in the future.
 
 I don't get it. distances are for instance per definition always
 positive if we have a concrete list of types that are always signed
 or unsigned and we stick to it then we'd have more then now:
 A documentation and guide for datatypes.

distances are a good example since they can very well be negative:

 dist = a - b;

this perfectly valid code will awfully break if b is larger than a 
and dist is defined unsigned. For the CPU and the compiler it wouldn't
make any difference, only the outcome would be wrong.

  In the worst case the problem only becomes apparent under rare
  circumstances and is not even caught during the development process.
 
 Yes, this might happen though I consider that unlikely.

then have a look at some of the bugs reported in plug-ins lately. They
have been reported years after the first release and didn't get caught
because they only showed up when the plug-in was used on small images
(width  64 || height  64). Such a bug could very well be caused by
the use of an unsigned variable.


Salut, Sven
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-05 Thread Kelly Martin

On Wed, Dec 05, 2001 at 01:11:56AM +0100, [EMAIL PROTECTED] wrote:

 I say using a type that represents the actual type of the value
 closely is a feature and not a bug. What wrong about seing:
 Hey, this value is supposed to be unsigned?

Because that's not what unsigned does in C.  Unsigned is a promise
to the compiler by the programmer; don't make the promise if you're
not certain you can.  The compiler doesn't enforce type safety with
respect to unsigned (except very trivially).

-- 
 I love catnip mice.
   It's why I chew their heads off.
 They're good for breakfast.
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread Sven Neumann

Hi,

[EMAIL PROTECTED] writes:

 IMHO not because you're abusing the real value for errors and thus one
 variable for 2 purposes which is a bad idea and using signed integers is
 dragging down performance.
 
 It is also a bad idea to use signed integers for most loops for example;
 unsigned int i;
 for (i = 0; i  width; i++)
   foo ();
 
 tends to be more efficient in some cases (depending on the use of i)
 then when categorily using signed ints.

this is not true. Please stop spreading this nonsense about unsigned
integers being more performant than signed ones. Go and write yourself
a simple benchmark for the code you mentioned above and you will
notice that it doesn't make any difference at all.

  you also removed a good bunch of debugging code that might still be
  needed (Kelly is working on this code) and unsignified lots of
  integers, which is why I choose to revert the changes in this file in
  a whole.
 
 The debugging cruft is pretty worthless, something to be added if really
 needed.

yes, but it is not nice to remove it while Kelly was working on this
part of the code.

  I do hope you will post the tile_manager_get_tile_num()
  part of your change to the list.
 
 Actually it makes only sense when using unsigned variables because
 otherwise the optimisation is mostly gone. If we can agree that nrows
 and ncols are unsigned then I'm willing to post the patch here
  
  If code makes assumptions about parameters (like for example assuming
  that width is  0), there has to be code like g_return_if_fail() to
  check this assumption. Defining width as an unsigned integer would
  also guarantee this, but it unneededly introduces a possibility for a
  bug if width is ever used in a subtraction.
 
 Not in the subtraction itself, only if the destination is also unsigned
 and if one expects a positive result and gets a negative one there's a
 bug in the code anyway.

the side effects of unsigned integers are not what people are used to
think about when designing an algorithm. You are changing the
mathematical base in an unneeded and hardly foreseeable way. Code that
looks correct and used to work fine, suddenly starts to behave
wrong. I doubt that you've checked each and every usage of the
variables you changed lately.

IMO using unsigned integers is a concept from the stone-age of
programming when CPUs and compilers used to be crap and the use of
unsigned values gave a real speed gain.

 FWIW I've converted lots of parameters and variables in paint-funcs to
 unsigned and I've experienced a 2,5% object code reduction in this part
 of the GIMP and since the calculations were simplified by the compiler
 (proven by assembly examination) it's for sure also faster though it's
 quite hard to profile this code since there's no benchmark generating
 reproducible results.

what are you aiming for, GIMP-embedded? You are speaking about ~1.3 KB
of object size reduction. This is ridiculous and there are certainly
other parts of The GIMP that can be made much slimmer with a less
error-prone approach. I also doubt that the code size reduction or
speed improvement originates in the use of unsigned variables. It
would surprise me very much if it would make any difference for the
compiler. Signed and unsigned variables are treated the same in almost
all situations.

If you are about to optimize parts of the GIMP, the first thing you
should do is write a test suite and benchmarking facility for this
part of The GIMP. No optimization should be allowed without such a
test suite.

 I still think GIMP is too fat and the code in parts too ugly. Though my
 changes in general just show small improvements I usually also fix
 stylistic problems and find unoptimal code and bogosity during the
 audits. Having a clear view what a function does and which parameters
 it expects is pretty important and correctly typing their arguments
 is a good step forward in achieving quality code which always runs
 at maximum speed.

Well, going through the code like a berserk doesn't really help here.
First, it is way too early to start optimizing the code in a whole.
Then, only code that is finished, working and stable should be
optimized to make it possible to catch errors introduced by the
optimizations.  Last, only code that showed up in a profile is worth
to be optimized.

What needs to be done at the moment is to give the GIMP core a
well-defined structure, to document and to debug it. A few small
encapsulated areas like the paint-funcs can be optimized now and if
benchmarks proove that the use of unsigned variables speeds things up,
then use them there for god's sake. But please, stop going over other
peoples code that you don't understand and stop applying your so
called optimizations to it. Thank you.


Salut, Sven



___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread degger

On  3 Dec, Robert L Krawitz wrote:

 Why?  If a function is explicitly documented as returning an error,
 it's the caller's responsibility to handle it.

Right.

 The callee often doesn't know the high level context to handle it in a
 useful fashion.

I'm talking about nested function calls. If a function deep inside fails 
it should be handled as quickly as possible instead of propagating it
through the code.

--
Servus,
   Daniel

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread degger

On  3 Dec, Robert L Krawitz wrote:

 By how much?

Depends on the code and the compiler. And the range I'm talking about
is usually between 0 and 50% improvement in both code and size.

 If it can't be measured, it's probably not enough to be
 worthwhile.

Aside from the gains it's IMHO also cleaner. The gcc and linux kernel
people handle it the same way btw.

 And if you use explicit error returns (which may require
 an additional pointer to be passed in), you'll quickly eat up any
 performance gain you might achieve.

No, the tile-manager change I did shows this pretty clear. Although 
using another parameter the object size is smaller here. If I get around
to do so I'll check the difference for a few more architectures here.
 
 Using signed integers also catches a particularly common error case
 (subtracting a value from a smaller value) that otherwise has to be
 checked for explicitly, which is also going to require more
 instructions (and even worse on modern processors, branches).

I doubt it. If negative numbers are likely to happen then the code
has to check for it anyway and thus the unsignedness of the single
parts of the calculation don't make any difference. And further modern
processors have conditional instructions which can be exactly used
for such kind of expressions and the more simple the check the easier
it is for the compiler to apply them. It is easier to check any type
agains 0 for example than against negativeness and this part also plays
a role when returning 0 or non-null instead of a negative value.

 Anyway, integer arithmetic (additions and subtractions) is usually one
 cycle (plus however long it takes to retrieve the operands and
 instruction from memory, cache, whatever) on modern processors, so
 it's hard for me to see how unsigned arithmetic is going to help.

That's correct, the CPU doesn't care about signedness. But by telling
the compiler that a value is unsigned it can apply additional
optimisation and it also simplifies some calculations considerably.
For example if you shift a signed value it has to generate code to
take care of the sign and similar with some logic operations.

 Fine, but
 
 a = c - d;
 if (a  0)
   abort()
 
 is likely to be more efficient than
 
 if (c  d)
   abort()
 else
   a = c - d

As this stands it is absolutely correct. However this is only a part of
the picture. The question is: What will happen in the rest of the code?
Also no one would prevent you from making a signed if you suspect a
to be negative. There's a lot of code where it is given that some value
is positive for example because it is used in loops which start from 0
all over the place. 

I'm not argueing about signed values in general but about variables
which are by purpose defined to be unsigned.
 
 And yes, maybe there's a bug in the code, but isn't it better to have
 a reasonably easy way of catching it?  If you put assertions in the
 code, they can be compiled in during debugging, and then turned off
 (thereby not consuming any extra time) when the code is solid.

One may or may not like the way Linus Torvalds codes but his programming
has definitely quite some style and elegance and one of his points is
only to have checks where you expect errors to happen instead of all
over the place. Putting assertions in there to catch problems in the
development phase is definitely a good idea and once the code is
stable they'll ressolve into nops and all that's left is efficient code;
that's how it should work.

 Get some numbers first before worrying about micro-optimizations like
 this.

I would if I could.

 Code that looks simpler isn't necessarily faster, and in

Trust me, if I see the assembly I can tell you which one is faster and
by which magnitude. As you already said most arithmetic calculations 
are one-cycler on modern CPUs and seldomly have sideeffects while
memory accesses in general are slow; if the assembly shows fewer memory
accesses AND fewer calculations while the branches are unaffected there
would have to been serious pipeline issues (because of dependencies) in
the code to make it slower.

 particularly it may not be *significantly* faster.  You're better off
 looking for hot spots in the code; if this isn't a hot spot, it
 doesn't matter what you do.

Oh, paint-funcs are a hotspot, it's quite easy to drag a fast machine
down by painting with a big brush in a transparent layer for instance;
most of the time is then spent in the combine_* functions which is
(as it is now) slow and I'm looking to speed that up by changing the
algorithm; still the basic calculations will remain the same so speeding
them up while brushing up the code is IMHO not a bad idea. Anyway, we're
talking about stuff here that's partially done.

 I've done some stuff like this in Gimp-print (although I haven't found
 unsigned vs. signed to matter very much, unless I can replace a
 division by a power of two by a right shift, in which it's sometimes
 worthwhile to take the branch penalty), but 

Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread degger

On  4 Dec, Sven Neumann wrote:

 this is not true. Please stop spreading this nonsense about unsigned
 integers being more performant than signed ones. Go and write yourself
 a simple benchmark for the code you mentioned above and you will
 notice that it doesn't make any difference at all.

Heck, you clearly demonstrate that you've no idea what you're talking 
about. unsinged types are not necessarily leading to faster code
but they sometimes enable better optimisation possibilities for the
compiler because every single fact the compiler knows aditionally about
types or functions like pureness, constness or staticness (of functions)
will lead to additionally hints the compiler notes in is internal
representation and will lead to more optimal code for the narrowed
purpose.

Check the code if you don't believe it. 

 yes, but it is not nice to remove it while Kelly was working on this
 part of the code.

Yes, that wasn't nice, apologies to Kelly. though I can imagine
better forms of debugging code than commented out printf's

 the side effects of unsigned integers are not what people are used to
 think about when designing an algorithm. You are changing the
 mathematical base in an unneeded and hardly foreseeable way. Code that
 looks correct and used to work fine, suddenly starts to behave
 wrong. I doubt that you've checked each and every usage of the
 variables you changed lately.

I was about to check in another followup patch which would have
cleared some of the maybe-problems this might have created though
you can scratch this idea now.
 
 IMO using unsigned integers is a concept from the stone-age of
 programming when CPUs and compilers used to be crap and the use of
 unsigned values gave a real speed gain.

Right, we should just use signed values and scratch all inlines, and
consts since compilers are clever enough to figure it out anyway.
Are you really believing what you're saying? When Marc and I where
experimenting at Mitchs place we figured out that providing additional
hints to gcc via non-portable attributes gave the compiler quite some
chances to optimise better it was you who said that we might want to
add this in macroized form to GIMP and now you're telling that compilers
are clever enough anyway to not get any advantages from such hints?

 what are you aiming for, GIMP-embedded? 

Actually yes.

 You are speaking about ~1.3 KB
 of object size reduction. This is ridiculous and there are certainly
 other parts of The GIMP that can be made much slimmer with a less
 error-prone approach. I also doubt that the code size reduction or
 speed improvement originates in the use of unsigned variables.

This was part of a general cleanup to better understand where the flow
can be optimised, it wasn't meant to be the huge-improvement-for-free
change but I also had cleaness and optimisation in mind when doing so.

 It would surprise me very much if it would make any difference for the
 compiler.

It surprises me that you're surprised instead of checking the situation
in real life.

 Signed and unsigned variables are treated the same in almost
 all situations.

I'd restrict that to many situations.

 If you are about to optimize parts of the GIMP, the first thing you
 should do is write a test suite and benchmarking facility for this
 part of The GIMP.

Bad luck, not from me.

 No optimization should be allowed without such a test suite.

I disagree, there are for sure many algorhythms which can be
optimised complexity wise and with micro changes but flow changes
can hardly be benched without a macro benchmark and since you 
object to branches in CVS there's hardly any way this will ever 
happen since once cannot do major surgery in the flow without having
a change to do it in smaller steps.

Anyway, since no benchmark is available and the hooks to add one
are rather unsatisfying one will have to use indicators to optimise.
I'm personally using gprof, gcov, gcc -save-temps and diff to tell
whether an improvement is there. You don't want optimisation - then 
go without it; not my problem

 Well, going through the code like a berserk doesn't really help here.

Great, so this is your word to stop doing so as well?

 First, it is way too early to start optimizing the code in a whole.

I disagree, for microscopic changes out of nowhere - yes, but I
had some bigger plans in mind.

 Then, only code that is finished, working and stable should be
 optimized to make it possible to catch errors introduced by the
 optimizations. 

 Last, only code that showed up in a profile is worth to be optimized.

You're telling me that? Surprising, I remember it was you who asked
me how to profile code, right?

 What needs to be done at the moment is to give the GIMP core a
 well-defined structure, to document and to debug it.

I have a smallish patch to document the functions and structures
I've been modifying, but since cleaness doesn't seem to be a valid
point except when it comes to GObjects - so be it.

 A 

Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread pcg

On Tue, Dec 04, 2001 at 02:17:06PM +0100, [EMAIL PROTECTED] wrote:
 agains 0 for example than against negativeness and this part also plays
 a role when returning 0 or non-null instead of a negative value.

Sorry, but before you continue with all this, ehrm, wrongness, would you
please first check what you are talking about? Can you give us a single
example of such a cpu? No cpu linux runs on has this property, btw.

The reason nobody wants to talk reasonable with you is that most of what
you claim is simply that: wrong. People cannot trust what you say when
they cna trivialy verify most of you claims as wrong. If you would only
give the points that _are_ true, then people will be much more open in
discussing optimizations.

 For example if you shift a signed value it has to generate code to
 take care of the sign and similar with some logic operations.

Again, not on any cpu that linux runs on.

 Trust me, if I see the assembly I can tell you which one is faster and
 by which magnitude.

How can we trust you if most of the easily-verifiable claims of yourself
are simply untrue?

*please* this is not a with-hunt. *please* re-adjust your attitude. when so
many people tell you that you are wrong you could at least check wether tzhis
is true.

-- 
  -==- |
  ==-- _   |
  ---==---(_)__  __   __   Marc Lehmann  +--
  --==---/ / _ \/ // /\ \/ /   [EMAIL PROTECTED]  |e|
  -=/_/_//_/\_,_/ /_/\_\   XX11-RIPE --+
The choice of a GNU generation   |
 |
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



[Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread Carol Spears

Hi Rebecca,
[EMAIL PROTECTED] (2001-12-04 at 1737.58 +0100):
 
 Can't we all bask in the gimp love?
 
Not to split hairs, but isn't it gimplove with no space?

carol

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread Kelly Martin

On Tue, Dec 04, 2001 at 11:34:59AM +0100, Sven Neumann wrote:
 the side effects of unsigned integers are not what people are used to
 think about when designing an algorithm. You are changing the
 mathematical base in an unneeded and hardly foreseeable way. Code that
 looks correct and used to work fine, suddenly starts to behave
 wrong. I doubt that you've checked each and every usage of the
 variables you changed lately.

There are places in tiles, tile managers, and pixel regions that use
negative numbers in unexpected ways (for example, theres's a spot in
the shapeburst code that uses a negative rowstride to go backwards
through an image buffer).  Changing these variables to unsigned will
obviously break things.

 If you are about to optimize parts of the GIMP, the first thing you
 should do is write a test suite and benchmarking facility for this
 part of The GIMP. No optimization should be allowed without such a
 test suite.

I can't agree more with this.  Profile the GIMP before you try
optimizing it.  You may be surprised to discover where the GIMP spends
most of its CPU time.  And trying to optimize a moving code base is
just plain stupid.

Kelly


-- 
 I love catnip mice.
   It's why I chew their heads off.
 They're good for breakfast.
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread Kelly Martin

On Tue, Dec 04, 2001 at 01:39:36PM +0100, [EMAIL PROTECTED] wrote:

 I'm talking about nested function calls. If a function deep inside fails 
 it should be handled as quickly as possible instead of propagating it
 through the code.

Uh, this is C, not Scheme.  We don't throw exceptions.  Calling
gimp_fatal_error is not an option in most cases (most errors are not
fatal).  The correct response to an error condition is to return an
error indication in accordance with your API.  Upstream callers are
responsible for checking error returns except for errors which cause
transfer-of-control with longjmp or exit.

-- 
 I love catnip mice.
   It's why I chew their heads off.
 They're good for breakfast.
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-04 Thread degger

On  4 Dec, Sven Neumann wrote:

 Check the code if you don't believe it. 
 
 Sorry, but that's exactly what I did before I posted the reply and I'm
 asking you to do that too. A simple benchmark prooves that the example
 you gave is wrong since the use of unsigned variables doesn't make any
 difference.

But you also do read my mails, do you? And I said clearly that it might 
make a difference in larger functions not that it necessarily betters 
anything.

Example? Ok, here you go, I subsituted an gint which is used for
a clearly positive range (1; length) by an guint. This is an arbitrary
example and doesn't give to much of a benefit though the function is
still simple.

--- paint-funcs.c.orig  Thu Nov 29 14:17:47 2001
+++ paint-funcs.c   Tue Dec  4 21:53:49 2001
@@ -343,7 +343,8 @@
   gdouble  sigma2;
   gdouble  l;
   gint temp;
-  gint i, n;
+  guinti;
+  gint n;
 
   sigma2 = 2 * sigma * sigma;
   l = sqrt (-sigma2 * log (1.0 / 255.0));

will lead to that difference in PPC assembly:

--- paint-funcs.backup.sTue Dec  4 21:52:45 2001
+++ paint-funcs.s   Tue Dec  4 21:53:57 2001
@@ -2298,7 +2298,7 @@
.align 3
 .LC5:
.long 0x4330
-   .long 0x8000
+   .long 0x0
.section.text
.align 2
.typemake_curve,@function
@@ -2361,7 +2361,6 @@
 .L1202:
mullw 0,30,30
neg 0,0
-   xoris 0,0,0x8000
stw 0,12(1)
stw 26,8(1)
lfd 1,8(1)

This is just to prove you that it can make a difference.

 I haven't said that and you will have noticed that we've added lots of
 consts to the code recently.

And this is a good thing. It might break stuff exactly like the
unsigned case but it will lead to better code and is much cleaner.

 I didn't say optimization is a bad thing. I just doubt that the use of
 unsigned variables is worth the risk of introducing bugs it certainly
 bears. There are exceptions, but definitely not in the UI part of the 
 code you've changed recently.

I wouldn't have touched the UI code if it was more seperate from the
rest.

 Bad luck, not from me.
 that, I call ignorance.

That I'd call lack of time and interest.

 No, since we announced that cleaning up the code is the major goal for
 1.4. The way we target this is (in this order):
 
  1. Move files into subdirectories that define subsystems and reduce 
 the dependencies between these subsystems.
  2. Clean up the code so it uses a common coding-style.
  3. Make the code bug-free (this should involve writing test suites 
 for the various subsystems).
  4. Profile it.
  5. Optimize it.
 
 Since we aren't even done with parts 1 and 2; can't you understand
 that we'd prefer not to start with 5 yet?!

Sure, but the changes were also part of your point 2, and it's never
to early to work on cleanliness.

 I didn't object to any of your modifications in the paint-funcs.

Great, but still I'm rather unhappy about the recent happenings and
that all of it happened in the public; you don't even respond to
private email.

 I'd say it's up to you at this point to proove your arguments. I've
 done my homework and benchmarked the use of unsigned vs. signed.

Don't even try to catch a difference using a synthetic microbenchmark;
do it on real code and you will see that it makes a difference.

Just to notice another thing before people start complaining, the
example above was done on PPC with gcc-2.95.4, any other architecture
or compiler might have different results but it's important to add
that any detoriation is a bug in the compiler so if done properly there
are only advantages to be had from it.

--
Servus,
   Daniel

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



[Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread degger

On  3 Dec, Sven Neumann wrote:

 you recently checked in a huge change to GIMP that we (Mitch and me)
 have been very unhappy with. In the meantime, I have gone through the
 hassle of looking at every single line of your changes and I have
 reverted most of it. Here are the reasons, why we think your
 optimizations don't make sense and, even worse, are dangerous:

BTW: It would have been a single command for me to revert the changes
but since you decide to work everything on your own.

 While unsigned variables can speed things up under very special
 circumstances,

Not special, in many circumstances.

 they bear the danger of introducing subtle bugs that
 are almost impossible to find. A good example is found in
 pango/docs/TEXT/coding-style (a recommened read, btw.):
  
   If width is unsigned and 10, then:
 
int new_width = MAX (width - 15, 1);
 
   produces 4294967291, not 1.

This is clearly a bug in the code. There are sizes which are by
definition unsigned and code computes an negative value this is
about as harmful as an big positive one.

 Also, in lots of places you've changed, the value -1 was used to 
 indicate an unset value (width and height of GimpPreview for 
 example).

Shouldn't be. I was about to go even further and change all false uses
of such values. What you imply is that using unsigned types for unsigned
values is wrong because you also use them for errorindication and this
(together with magic constants) is about most of the evilness of
programming.

 use bitfields in structs where possible
 
 this is an optimizations of structs sizes. It does make sense to use
 bitfields for boolean fields if large numbers of this struct are
 allocated. For rarely used objects the gain in memory usage is
 neglible however.

It's not only the memory consumption, it's also the addressing which is
much faster (normally) for bitfields because one can read several states 
at once while the access is realised with masking instead of several
memory reads (or writes) and as such using bitfields has several huge
advantages:

- Less memory accesses (and all the results thereof)
- Smaller objects because of less code
- Implied error checking against abuse by the compiler

My only worry here was that some compilers don't support them but since
you started using them in other files I didn't see any problem with
this. 

 Since the change makes the code less readable it should be applied
 with care.

I disagree strongly here. The code itself doesn't change and structure
definitions tend to win when it comes to readability here.

 The change again also bears the possibility of introducing bugs.

I see it the other way. It bears the possibility to detect unseen bugs.

 This happens when values others than TRUE (1) and FALSE (0) are
 assigned to struct fields defined as unsigned int : 1.

What do you expect to happen then?

 For this reason, this change should only be done
 late in the development cycle. Once the API is settled and the code is
 stable, we can think about converting booleans in frequently used
 structs to bitfields. At the very moment, it doesn't make sense at
 all.

Well, your thought.

 you changed code from
  gimp-be_verbose = be_verbose ? TRUE : FALSE;
 to 
  gimp-be_verbose = be_verbose;
 
 This is wrong, especially if a bitfield is used. I don't think I need
 to explain the reason.

It doesn't even make sense when NOT using bitfields but I definitely see
no problem when doing so. Please don't always assume I see what you mean
by telling this is wrong; if you see a problem here tell me so.

 Daniel, would you please from now on inform us about the changes you
 are working on and send patches to this mailing list instead of
 applying your work to CVS without asking. It took me hours to revert
 your changes and I don't want to have to go through this again. If you
 think I reverted too much (which I'm sure has happened in a few
 places), please send the relevant changes in small patches so we can
 discuss them here.

You not being able to use CVS efficently doesn't make me a bad person.
Maybe you would have saved you a lot of time if you simply asked me
to revert the (still correct) changes. 

Anyway, since you seem to like to develop on your own because you know
everything better anyway; feel free to do so. I don't care whether
correct code shines off your ass or you have the Saft but putting
embargos up to me because you don't understand what I'm trying to
achieve is just likely to piss off another of the few coders left.

BTW: Not that I've never corrected any of yours or Mitches code
resulting from a thinko or type...

It's up to you.

--
Servus,
   Daniel

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread Michael Natterer

[EMAIL PROTECTED] writes:

If width is unsigned and 10, then:
  
 int new_width = MAX (width - 15, 1);
  
produces 4294967291, not 1.
 
 This is clearly a bug in the code. There are sizes which are by
 definition unsigned and code computes an negative value this is
 about as harmful as an big positive one.

This is not a bug in the code, it's only a bug if the code uses
unsigned. Why on earth should we introduce side conditions that make
using perfectly ok code like above buggy? Using signed is just
defensive programming, using unsigned introduces side effects that are
hard to find.

  Also, in lots of places you've changed, the value -1 was used to 
  indicate an unset value (width and height of GimpPreview for 
  example).
 
 Shouldn't be. I was about to go even further and change all false uses
 of such values. What you imply is that using unsigned types for unsigned
 values is wrong because you also use them for errorindication and this
 (together with magic constants) is about most of the evilness of
 programming.

I don't see why the type preview size which is defined as
size of the preview if = 0, or undefined otherwise is bad.
What special value would you introduce instead?

  This happens when values others than TRUE (1) and FALSE (0) are
  assigned to struct fields defined as unsigned int : 1.
 
 What do you expect to happen then?

The following will happen:

struct eek
{
  guint argh : 1;
};

void
foobar (struct eek eek,
gboolean   baz)
{
  eek.argh = baz;
}

Now calling foobar(my_eek, 2);

will result in my_eek.argh being 0 (the least significant bit of 2).

Assigning to a gboolean (which is a *signed* int) will assign 2
and still be TRUE in the C sense.

  you changed code from
   gimp-be_verbose = be_verbose ? TRUE : FALSE;
  to 
   gimp-be_verbose = be_verbose;
  
  This is wrong, especially if a bitfield is used. I don't think I need
  to explain the reason.
 
 It doesn't even make sense when NOT using bitfields but I definitely see
 no problem when doing so. Please don't always assume I see what you mean
 by telling this is wrong; if you see a problem here tell me so.

It makes sense and kindof *must* be used for unsigned bitfields. See above.

Furthermore, I don't see a reason for being pissed of. If you announced
what you were about to do we could have discussed it beforehand.

ciao,
--Mitch
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread Sven Neumann

Hi,

[EMAIL PROTECTED] writes:

 However I see much room for improvement here. The values I changed
 to unsigned are likely meant to be unsigned like sizes, distances or
 heights or widths. And those are frequently used in loops like
 
 int i;
 for (i = 0; i  width; i++)
   foo ();
 
 if we were to expect negative values in this case we'd be really doomed
 and as such I consider it a feature to be warned by the compiler if a
 calculation is definitely underflowing or tests are useless.
 Negative values do have a right to exist when it comes to coordinates
 but using signed types for error reporting AND value represantation
 at the same time is likely to be errorprone.

Using them for error reporting is definitely a bad idea. Using a negative
value to indicate that a value has not been set and needs to be computed
is IMO a reasonable usage.

 I propose to do it the following way:
 gboolean do_something (guint *value, ...)
 
 (means passing a pointer to the place the result should be written to)
 
 instead of 
 gint do_something (...)
 and returning a negative value in case of failure

yes!

 I've applied exactly this scheme to tile_manager_get_tile_num () in 
 tile-manager.c and together with replacing the ongoing errorchecking
 throughout the callees was able to save a whooping 480 bytes in object
 size on PPC and got faster code while (IMHO) making the code clearer.

you also removed a good bunch of debugging code that might still be
needed (Kelly is working on this code) and unsignified lots of
integers, which is why I choose to revert the changes in this file in
a whole. I do hope you will post the tile_manager_get_tile_num()
part of your change to the list.

 I do because one has to constantly check for errorvalues and there 
 lies one problem; we have several places in the GIMP where return 
 values are checked for errors and then passed down to another function
 where they are checked again while there are also places where we don't
 have error checking at all.

Do we? We do have a lot of g_return_val_if_fail() statements all over
the place, but this is for debugging purposes only and should be
disabled for production code. No such call should ever be triggered;
if it is, there's a bug. For this reason, the caller does not need to
check for values returned by g_return_val_if_fail(). The whole purpose
of these statements is to catch bugs early.

If code makes assumptions about parameters (like for example assuming
that width is  0), there has to be code like g_return_if_fail() to
check this assumption. Defining width as an unsigned integer would
also guarantee this, but it unneededly introduces a possibility for a
bug if width is ever used in a subtraction.

 Using signed types is unelegant and prevents the compiler from
 optimising the code better. NULL pointers have the nice property of
 being easy to check and I think it's a nice idea to have functions
 return 0 or !0 aka TRUE or FALSE instead of some bogus values
 because it's clearer and faster.

I agree about the return value thing, but I doubt the use of signed or
unsigned makes up for any noticeable speed difference expect under
very rare conditions. Before any integer is changed to an unsigned
value, a benchmark should proove that it really is an optimization and
all code using the value needs to be reviewed carefully.


Salut, Sven

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread degger

On  4 Dec, Sven Neumann wrote:

 Using them for error reporting is definitely a bad idea. Using a
 negative value to indicate that a value has not been set and needs to
 be computed is IMO a reasonable usage.

IMHO not because you're abusing the real value for errors and thus one
variable for 2 purposes which is a bad idea and using signed integers is
dragging down performance.

It is also a bad idea to use signed integers for most loops for example;
unsigned int i;
for (i = 0; i  width; i++)
  foo ();

tends to be more efficient in some cases (depending on the use of i)
then when categorily using signed ints.

 you also removed a good bunch of debugging code that might still be
 needed (Kelly is working on this code) and unsignified lots of
 integers, which is why I choose to revert the changes in this file in
 a whole.

The debugging cruft is pretty worthless, something to be added if really
needed.

 I do hope you will post the tile_manager_get_tile_num()
 part of your change to the list.

Actually it makes only sense when using unsigned variables because
otherwise the optimisation is mostly gone. If we can agree that nrows
and ncols are unsigned then I'm willing to post the patch here
 
 If code makes assumptions about parameters (like for example assuming
 that width is  0), there has to be code like g_return_if_fail() to
 check this assumption. Defining width as an unsigned integer would
 also guarantee this, but it unneededly introduces a possibility for a
 bug if width is ever used in a subtraction.

Not in the subtraction itself, only if the destination is also unsigned
and if one expects a positive result and gets a negative one there's a
bug in the code anyway.

 I agree about the return value thing, but I doubt the use of signed or
 unsigned makes up for any noticeable speed difference expect under
 very rare conditions. Before any integer is changed to an unsigned
 value, a benchmark should proove that it really is an optimization and
 all code using the value needs to be reviewed carefully.

FWIW I've converted lots of parameters and variables in paint-funcs to
unsigned and I've experienced a 2,5% object code reduction in this part
of the GIMP and since the calculations were simplified by the compiler
(proven by assembly examination) it's for sure also faster though it's
quite hard to profile this code since there's no benchmark generating
reproducible results.

I still think GIMP is too fat and the code in parts too ugly. Though my
changes in general just show small improvements I usually also fix
stylistic problems and find unoptimal code and bogosity during the
audits. Having a clear view what a function does and which parameters
it expects is pretty important and correctly typing their arguments
is a good step forward in achieving quality code which always runs
at maximum speed.

--
Servus,
   Daniel

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread degger

On  4 Dec, Sven Neumann wrote:

 Using them for error reporting is definitely a bad idea. Using a
 negative value to indicate that a value has not been set and needs to
 be computed is IMO a reasonable usage.

On a side note: I found it quite often that the return value is set
to something in case it's real value couldn't be computed, this is 
also some form of error indication which I'd like to avoid: A function
fails or succeeds and in either case appropriate steps have to be taken;
just propagating the error code down to the original caller in the hope
to catch it there is IMHO a bad idea.

--
Servus,
   Daniel

___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread Robert L Krawitz

   From: [EMAIL PROTECTED]
   Date: Tue, 4 Dec 2001 01:57:26 +0100 (CET)

   On  4 Dec, Sven Neumann wrote:

Using them for error reporting is definitely a bad idea. Using a
negative value to indicate that a value has not been set and needs to
be computed is IMO a reasonable usage.

   IMHO not because you're abusing the real value for errors and thus
   one variable for 2 purposes which is a bad idea and using signed
   integers is dragging down performance.

By how much?  If it can't be measured, it's probably not enough to be
worthwhile.  And if you use explicit error returns (which may require
an additional pointer to be passed in), you'll quickly eat up any
performance gain you might achieve.

Using signed integers also catches a particularly common error case
(subtracting a value from a smaller value) that otherwise has to be
checked for explicitly, which is also going to require more
instructions (and even worse on modern processors, branches).

Anyway, integer arithmetic (additions and subtractions) is usually one
cycle (plus however long it takes to retrieve the operands and
instruction from memory, cache, whatever) on modern processors, so
it's hard for me to see how unsigned arithmetic is going to help.

If code makes assumptions about parameters (like for example
assuming that width is  0), there has to be code like
g_return_if_fail() to check this assumption. Defining width as an
unsigned integer would also guarantee this, but it unneededly
introduces a possibility for a bug if width is ever used in a
subtraction.

   Not in the subtraction itself, only if the destination is also
   unsigned and if one expects a positive result and gets a negative
   one there's a bug in the code anyway.

Fine, but

a = c - d;
if (a  0)
  abort()

is likely to be more efficient than

if (c  d)
  abort()
else
  a = c - d

And yes, maybe there's a bug in the code, but isn't it better to have
a reasonably easy way of catching it?  If you put assertions in the
code, they can be compiled in during debugging, and then turned off
(thereby not consuming any extra time) when the code is solid.

I agree about the return value thing, but I doubt the use of
signed or unsigned makes up for any noticeable speed difference
expect under very rare conditions. Before any integer is changed
to an unsigned value, a benchmark should proove that it really is
an optimization and all code using the value needs to be reviewed
carefully.

   FWIW I've converted lots of parameters and variables in paint-funcs
   to unsigned and I've experienced a 2,5% object code reduction in
   this part of the GIMP and since the calculations were simplified by
   the compiler (proven by assembly examination) it's for sure also
   faster though it's quite hard to profile this code since there's no
   benchmark generating reproducible results.

Get some numbers first before worrying about micro-optimizations like
this.  Code that looks simpler isn't necessarily faster, and in
particularly it may not be *significantly* faster.  You're better off
looking for hot spots in the code; if this isn't a hot spot, it
doesn't matter what you do.

I've done some stuff like this in Gimp-print (although I haven't found
unsigned vs. signed to matter very much, unless I can replace a
division by a power of two by a right shift, in which it's sometimes
worthwhile to take the branch penalty), but I've spent a lot of time
with the profiler to actually find the real hot spots.  Simply moving
constant computations out of loops (into a lookup table, or some such)
often saves a lot more time than any of this bit fiddling.

   I still think GIMP is too fat and the code in parts too
   ugly. Though my changes in general just show small improvements I
   usually also fix stylistic problems and find unoptimal code and
   bogosity during the audits. Having a clear view what a function
   does and which parameters it expects is pretty important and
   correctly typing their arguments is a good step forward in
   achieving quality code which always runs at maximum speed.

I agree, but that's exactly why this kind of micro-optimization is
premature.  You'll get much better results looking for the hot spots
first, and understanding exactly what's going on and how you can
devise an overall more efficient approach, than by blindly converting
signed ints to unsigned and using bit fields.

-- 
Robert Krawitz [EMAIL PROTECTED]  http://www.tiac.net/users/rlk/

Tall Clubs International  --  http://www.tall.org/ or 1-888-IM-TALL-2
Member of the League for Programming Freedom -- mail [EMAIL PROTECTED]
Project lead for Gimp Print/stp --  http://gimp-print.sourceforge.net

Linux doesn't dictate how I work, I dictate how Linux works.
--Eric Crampton
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer



Re: [Gimp-developer] Re: your so called optimizations and why we don't like them

2001-12-03 Thread Robert L Krawitz

   From: [EMAIL PROTECTED]
   Date: Tue, 4 Dec 2001 02:01:22 +0100 (CET)

   On  4 Dec, Sven Neumann wrote:

Using them for error reporting is definitely a bad idea. Using a
negative value to indicate that a value has not been set and needs to
be computed is IMO a reasonable usage.

   On a side note: I found it quite often that the return value is set
   to something in case it's real value couldn't be computed, this is
   also some form of error indication which I'd like to avoid: A
   function fails or succeeds and in either case appropriate steps
   have to be taken; just propagating the error code down to the
   original caller in the hope to catch it there is IMHO a bad idea.

Why?  If a function is explicitly documented as returning an error,
it's the caller's responsibility to handle it.  The callee often
doesn't know the high level context to handle it in a useful fashion.

-- 
Robert Krawitz [EMAIL PROTECTED]  http://www.tiac.net/users/rlk/

Tall Clubs International  --  http://www.tall.org/ or 1-888-IM-TALL-2
Member of the League for Programming Freedom -- mail [EMAIL PROTECTED]
Project lead for Gimp Print/stp --  http://gimp-print.sourceforge.net

Linux doesn't dictate how I work, I dictate how Linux works.
--Eric Crampton
___
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer