POV-Ray : Newsgroups : povray.programming : Improved intersection routine for CSG-Intersection objects Server Time
6 Oct 2024 22:11:33 EDT (-0400)
  Improved intersection routine for CSG-Intersection objects (Message 71 to 80 of 108)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Warp
Subject: Re: [OT] Re: Improved intersection routine for CSG-Intersection objects
Date: 16 Dec 2003 17:25:23
Message: <3fdf8653@news.povray.org>
Nicolas Calimet <pov### [at] freefr> wrote:
>         But in what language the C++ streams are implemented internally ?
> Isn't it mostly in C and asm ?  The C libraries usually are too.

>         I'm interested in this particular point since my own projects
> rely _a lot_ on labelled data (using my own C string "library").  Could you
> give an example where C++ strings clearly outperform the equivalent C code
> (if anything similar can be done) ?

  I think you are confusing "string" and "stream" above. They are two
quite different things... :)

  I was talking about std::string.
  Almost *any* operation on a std::string is faster than an equivalent
operation on a C string. The simplest example is getting the size
of the string.
  std::string::size() is a constant-time operation (it simply returns
the value of a variable), while strlen() goes through the entire string
to get its size. Now, imagine that the string is 100 million characters
long...

>         Ah ! Since I usually write GB of data, it seems that I still have
> a good reason to "kiss" C a bit longer  ;-)

  If you do it right, you can change from one to the other by changing
just a few lines of code (no matter how many millions of lines long is
your whole program). That's what modularity is about.
  (If you do it wrong and you want to change it, you'll have to go
through the millions of lines and change every place where it's
used... Remember y2k?-) )

-- 
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -


Post a reply to this message

From: Nicolas Calimet
Subject: Re: [OT] Re: Improved intersection routine for CSG-Intersection objects
Date: 16 Dec 2003 19:04:51
Message: <3fdf9da3$1@news.povray.org>
>   I think you are confusing "string" and "stream" above. They are two
> quite different things... :)

	Yes, it was a mistake: writing "stream" for "string" (see my answer
to Thorsten that I posted 3 minutes before your message  :-p )

>   I was talking about std::string.
>   Almost *any* operation on a std::string is faster than an equivalent
> operation on a C string. The simplest example is getting the size
> of the string.
>   std::string::size() is a constant-time operation (it simply returns
> the value of a variable)

	This example is very trivial, and you can easily implement the same
in your own string library in C.  What I'd like to see is the performance of
creating a dynamical formatted string, similarly to vsprintf() -- but of course
without the static buffer passed as argument, which makes vsnprintf unecessary.

>   (If you do it wrong and you want to change it, you'll have to go
> through the millions of lines and change every place where it's
> used... Remember y2k?-) )

	'sed'  ;-)

	- NC


Post a reply to this message

From: Warp
Subject: Re: [OT] Re: Improved intersection routine for CSG-Intersection objects
Date: 16 Dec 2003 20:24:52
Message: <3fdfb064@news.povray.org>
Nicolas Calimet <pov### [at] freefr> wrote:
>         This example is very trivial, and you can easily implement the same
> in your own string library in C.

  The advantage of the C++-way is that a std::string is more secure
(forget about memory leaks) and its syntax is simpler.

>  What I'd like to see is the performance of
> creating a dynamical formatted string, similarly to vsprintf() -- but of course
> without the static buffer passed as argument, which makes vsnprintf unecessary.

  std::stringstream is for that.

  std::stringstream works like a std::ostream (and like a std::istream)
but instead of outputting to a file it stores things given to it onto
memory as a string. You can then get that string from it.

  Since std::stringstream is inherited from std::basic_iostream, you
can use it anywhere a std::istream or a std::ostream is expected.

-- 
#macro N(D)#if(D>99)cylinder{M()#local D=div(D,104);M().5,2pigment{rgb M()}}
N(D)#end#end#macro M()<mod(D,13)-6mod(div(D,13)8)-3,10>#end blob{
N(11117333955)N(4254934330)N(3900569407)N(7382340)N(3358)N(970)}//  - Warp -


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: [OT] Re: Improved intersection routine for CSG-Intersection objects
Date: 17 Dec 2003 05:15:18
Message: <3fe02cb6$1@news.povray.org>
In article <3fdf9da3$1@news.povray.org> , Nicolas Calimet 
<pov### [at] freefr>  wrote:

>  This example is very trivial, and you can easily implement the same
> in your own string library in C.  What I'd like to see is the performance of
> creating a dynamical formatted string, similarly to vsprintf() -- but of
course
> without the static buffer passed as argument, which makes vsnprintf
unecessary.

If you really want to use printf-style formatting in C++ (I sure do so
often), take a look at <http://www.boost.org/libs/format/index.htm>.  While
I never used it (I have my own mini-utility function for that), it does
sound like a simple solution.

    Thorsten

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Wolfgang Wieser
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 13:51:42
Message: <3fe1f73d@news.povray.org>
Thorsten Froehlich wrote:
>> For inline functions this is true. Not so for extern linkage.
> 
> You cannot have external linkage for template functions.
> 
You can. You just have to make sure that a specialisation for the 
used type is linked in extenally. 

>> The result is lots of inline code which results in larger executables
>> and eventually even in slower code.
> 
> Only if you use containers of many different types!  Modern linkers will
> eliminate multiple identical template function instances, thus you only
> see the code bloat in the object files, but not in the final linked
> program.
> 
Correct. But all as you normally need to have all template stuff 
inline, this results in a lot of inline code duplication. 

>>>> But _not_ for real simple types. For "I quickly need a vector", using
>>>> double v[3] is still faster than anything using operator new or
>>>> applying a fancy con/destructor.
>>>
>>> Sorry, but if you need a local variable, who said you should use new???
>>>
>> So, if you need a local variable of just such a type we're talking about,
>> i.e. a class which simply contains a pointer to an internal class,
>> then the class will be allocated on the stack (okay, fast) and the
>> internal class will be allocated using operator new on the heap.
> 
> But only if there is data.  If properly designed, if there is no data, no
> memory should be allocated.  Unless you use fixed-size data in C, you will
> have exactly the same amount of work.  And there is nothing that keeps you
> from using fixed-size data in C++, except that it is bad style, in both
> languages.
> 
I have the feeling that we're not getting the point of what we want 
to tell each other... 

>> All that happens when you call the constructor and initialize your
>> class. For the normal use, this is just what you want because when
>> you pass the class to a function, it is quite fast (just increase
>> reference counter). But if the object is simply a local var you want
>> on the stack, then the overhead is considerably.
> 
> Why would you reference count the internal data of most classes?  You seem
> to be thinking about some special case, but even then, how would a
> reference counting C++ implementation be slower than a similar C
> implementation?
> 
Because the C construction does no reference counting. You allocate 
a pointer once and then use it. And the designer knows where it was 
allocated, "who" is responsible for the pointer and its lifetime. 

Yes, that's insecure like hell but faster and smaller. 
And for good designs, it even :) works...

> Well, you should really not be doing reference counting inside a class in
> the first place.  If you share data among several objects of the same
> class,
> most of the time you have a serious design problem.  And again, the
> reference counting would not work differently in C, so there is again no
> difference in overhead!
> 
I need to make an example. 

A fairly normal implementation of the class which just holds a 
pointer to an internal class. As the internal class may be shared 
among several instances, we use reference counting. 

class MyObject
{
        _MyInternalObject *o;
        MyObject(const MyObject &m) : o(m.o)
        {  if(o) o->add_reference();  }
        MyObject(params_for_obj)
        {  o=new _MyInternalObject(params_for_obj);  o->add_reference();  }
        ~MyObject()
        {  if(o) o->sub_reference();  }
};

This is fairly straight forward and how things like std::string, etc, 
work. 

Overhead at function call (call by value): just copying the pointer 
and adding a reference (i.e. ++ref_cnt;)
[Much better than call-by-value of the complete internal class but 
worse than simply passing a pointer/reference]

So, now say you need a temporary of that class: 

foo()
{
        MyObject obj(pbject_params);
        obj.do_sth();  return(obj.sth_else());
}

That will (1) allocate some bytes on the stack (fast) and then 
(2) allocate internal object using operator new (slow). 

That is what I had in mind. 

I still am the opinion that it is pretty hard if not (nearly?) impossible 
to design really fast C++ code (i.e. as fast as insecure C code) when one 
forces itself to stick to all the "good style" guidelines. (Depends on 
what one defines as "good style"). 

So, of course gained savety comes at some price. It's just to get it 
as cheap as possible. 

Wolfgang


Post a reply to this message

From: Wolfgang Wieser
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 13:55:43
Message: <3fe1f82f@news.povray.org>
Thorsten Froehlich wrote:

> In article <3fddcfb2@news.povray.org> , Warp <war### [at] tagpovrayorg>  wrote:
> Especially on Windos, but almost equally so on all others systems, there
> are so many specific things, trying to abstract them is a true waste of
> time
> unless a *very* small subset of all available functionality is used.  In
> short, it is much better to do one thing well than three or four things
> badly.
> 
Have a look at Qt. 

Wolfgang


Post a reply to this message

From: Wolfgang Wieser
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 14:06:44
Message: <3fe1fac3@news.povray.org>
Thorsten Froehlich wrote:
>> And for RTTI: I cannot imagine that a dynamic_cast has real little
>> overhead but I honestly hope that it is the case until I run a test
>> in the next days.
> 
> Effectively you only need it when using multiple inheritance.  Of course,
> if you depend on dynamic_cast heavily, you probably have some serious
> problem understanding C++.
> 
I wouldn't say that. It depends on the problem. 
Of course, virtualisation should be preferred where possible. 
Virtual function calls are cheap and fast (the ovherhead compared to 
normal external calls is negliable unless it's a just-return-value 
function in some inner loop). 

>> Okay, my observations quoted above were based on my experiences on the
>> gcc-2.7.3.2 -> gcc-2.8 transition and may very well be outdated.
> 
> One of the slowest known compilers around ... and outdated by half a
> decade.
> 
True. I just did not re-examine my observations from the past, so I am 
doing that now. 

>> So, RTTI and exceptions still introduce considerable overhead even if
>> not used.
> 
> Shitty compiler => shitty code!  You should really use professional
> compilers to base your comparisons on.  Gcc's main feature is portability,
> not performance.
> 
Heeee. gcc is by all means no "shitty compiler". But we may try using 
e.g. the intel compiler (it has -fno-rtti but no -fno-exceptions). 

Do you know how RTTI internally works? (I.e. in an "non-shitty" 
compiler.)

Wolfgang


Post a reply to this message

From: Wolfgang Wieser
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 14:16:52
Message: <3fe1fd24@news.povray.org>
Thorsten Froehlich wrote:

> In article <3fdce9c8@news.povray.org> , Wolfgang Wieser <wwi### [at] gmxde>
> wrote:
> 
>> First of all, the copy constructor and assignment operators will
>> introduce overhead:
>>
>> tempate<classT>
>>  auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<T>& rhs)
>>  {
>>    if (this != &rhs)
>>    {
>>      delete pointer;   // <-- if(pointer) { destruct & free }
>>      pointer = rhs.pointer;
>>      rhs.pointer = 0;
>>    }
>>    return *this;
>>  }
> 
> No, what you show introduces no overhead when used.  If you would do the
> same without an auto_ptr you would need to write exactly the same code.
> Consequently, there is no overhead - the code is just created for you
> rather than you having to write it.
> 
Well, there is no normally need to zero the pointer in the 
caller function and do all that fancy stuff. A raw pointer or reference 
will do in most cases. 

And I even can imagine situations where the fact that the pointer value 
in the caller it cleared during the call will lead to NULL ptr deref. 
Having sait that, you'll yell at me about bad design but one finds oneself 
much faster in that situation as one may think -- especially when using 
an auto_ptr as a class member. 

Wolfgang


Post a reply to this message

From: Wolfgang Wieser
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 14:23:12
Message: <3fe1fe9f@news.povray.org>
Warp wrote:

> Wolfgang Wieser <wwi### [at] gmxde> wrote:
>> So, if you need a local variable of just such a type we're talking about,
>> i.e. a class which simply contains a pointer to an internal class,
>> then the class will be allocated on the stack (okay, fast) and the
>> internal class will be allocated using operator new on the heap.
> 
>   I still not understand that if you want a container of static size
> why would be use a dynamic container for that.
>   Make a container with static size which does not allocate memory and
> there you are.
> 
Please have a look at the example code in the other posting nearby. 

Wolfgang


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: Improved intersection routine for CSG-Intersection objects
Date: 18 Dec 2003 15:19:11
Message: <3fe20bbf$1@news.povray.org>
In article <3fe1f73d@news.povray.org> , Wolfgang Wieser <wwi### [at] gmxde>  
wrote:

>>> For inline functions this is true. Not so for extern linkage.
>>
>> You cannot have external linkage for template functions.
>>
> You can. You just have to make sure that a specialisation for the
> used type is linked in extenally.

Well, you still need the whole template source code for the compiler to
work.  So, the code would still be generated locally and the linker may then
indeed decide to throw the local instance of the template functions away and
use the one from the outside, but this will hardly gain you anything but
problems with most compilers.

>> Only if you use containers of many different types!  Modern linkers will
>> eliminate multiple identical template function instances, thus you only
>> see the code bloat in the object files, but not in the final linked
>> program.
>>
> Correct. But all as you normally need to have all template stuff
> inline, this results in a lot of inline code duplication.

No, only the very common bad programming habit of placing template
implementation code inside classes instead outside causes template code to
be inlined (also a compiler is *not* required to inline anything!).

>> But only if there is data.  If properly designed, if there is no data, no
>> memory should be allocated.  Unless you use fixed-size data in C, you will
>> have exactly the same amount of work.  And there is nothing that keeps you
>> from using fixed-size data in C++, except that it is bad style, in both
>> languages.
>>
> I have the feeling that we're not getting the point of what we want
> to tell each other...

Could well be the case.

> Because the C construction does no reference counting. You allocate
> a pointer once and then use it. And the designer knows where it was
> allocated, "who" is responsible for the pointer and its lifetime.
>
> Yes, that's insecure like hell but faster and smaller.

Of course, nothing keeps you from doing this in C++ as well...


> That will (1) allocate some bytes on the stack (fast) and then
> (2) allocate internal object using operator new (slow).
>
> That is what I had in mind.

I almost assumed you did.  However, node that having just a pointer to an
"internal" object is just terrible design, and if you use this to hide
something "private" behind another interface, C++ is not the language you
want to be using!

Second, if you really have a valid need to frequently create temporary
copies of a specific class of objects, you will gain a really lot if you use
a memory pool (i.e. boost::pool for C++).  And of course, you will still
have the same problems when doing something similar in C.

> I still am the opinion that it is pretty hard if not (nearly?) impossible
> to design really fast C++ code (i.e. as fast as insecure C code) when one
> forces itself to stick to all the "good style" guidelines. (Depends on
> what one defines as "good style").

Yet, but you are making two major mistakes in your logic here: Just because
C++ allows you to use more secure programming methods does not imply in any
way that C++ is slow or slower than C.  It simply implies that a
well-programmed piece of code will have a tiny bit of overhead over a fast
hack.  And the languages features for good programming style only exist in
C++ but not C.  Thus you can only use them in C++, while you are stuck with
unstable code in C.

However, this is the case for any higher language level.  You can claim
exactly the same for C and your native assembler.  Of course, if you know
what you are doing you can still outperform even a very good compiler (the
SSE2 noise code in POV-Ray is a good example for this) by using lower level
programming languages, but that doesn't say anything about the higher level
languages!

    Thorsten

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.