speed versus OO

M

michael.goossens

For instance take: heavely used classes, lets say Vector(not the
dynamic datatype but a mathematical vector) and Point. They have both
3 class variables x, y and z and some functions they both use.

Now the question is, would subclassing these 2 classes have any
negative effect on the speed of a program that uses these classes very
frequently, i.e. the raytracer I'm building. So completely different
types of classes versus inheritance, which would be faster? Or doesn't
it matter.
My thought would be that its slower and the only gain is that its
easier in a conceptual way to use inheritance, but I don't need a good
design in the first place, I need speed!

I'm most likely not going to use inheritance for that reason but also
because those classes "have" to be differentiated from eachother. By
that I mean they can't just take over eachothers identity. Normal n =
v with v a Vector may not be possible, even used explicit to make
sure, and this kind of concretisation is what one loses by the
abstraction of the superclass no? Or is it my responsability not to
lose the identity of a class into the abstraction of the superclass.

I think I'm starting to get crazy about all the newly gained c++
information that I don't know where to put it all at once =). I'll get
myself some sleep first and maybe tomorow I'll be back on track.

Thanks already guys.
 
S

Salt_Peter

For instance take: heavely used classes, lets say Vector(not the
dynamic datatype but a mathematical vector) and Point. They have both
3 class variables x, y and z and some functions they both use.

Now the question is, would subclassing these 2 classes have any
negative effect on the speed of a program that uses these classes very
frequently, i.e. the raytracer I'm building. So completely different
types of classes versus inheritance, which would be faster? Or doesn't
it matter.
My thought would be that its slower and the only gain is that its
easier in a conceptual way to use inheritance, but I don't need a good
design in the first place, I need speed!

I'm most likely not going to use inheritance for that reason but also
because those classes "have" to be differentiated from eachother. By
that I mean they can't just take over eachothers identity. Normal n =
v with v a Vector may not be possible, even used explicit to make
sure, and this kind of concretisation is what one loses by the
abstraction of the superclass no? Or is it my responsability not to
lose the identity of a class into the abstraction of the superclass.

I think I'm starting to get crazy about all the newly gained c++
information that I don't know where to put it all at once =). I'll get
myself some sleep first and maybe tomorow I'll be back on track.

Inheritance is a special relationship. There should be no ambiguity
when deciding whether a set of classes should be classified in an
inheritance hierarchy. If Vector is_a Point (or coordinate), and you
can satisfy such a model logically, then inheritance might make sense.
I don't see it. A Vector needs an origin, yes. Thats composition.
Composition should be the default until proven otherwise (thats me,
some will disagree).

While inheritance is not needed in any way to write efficient C++
code, it does have benefits. And that is where the programmer needs to
analyze the design (with respect to extendeability, maintainability
and robustness).

What if you need a special kind of Point or/and a special kind of
Vector a year from now? Does your present model support extending
Point and Vector in the future?
Thats the question.
Depending on how you answer that question, you might decide to provide
abstract types, abstract interfaces, etc.
 
E

Erik Wikström

For instance take: heavely used classes, lets say Vector(not the
dynamic datatype but a mathematical vector) and Point. They have both
3 class variables x, y and z and some functions they both use.

Now the question is, would subclassing these 2 classes have any
negative effect on the speed of a program that uses these classes very
frequently, i.e. the raytracer I'm building. So completely different
types of classes versus inheritance, which would be faster? Or doesn't
it matter.

Maybe, the effects of inheritance will depend on the classes that you
inherit from and the class that inherits. In some situations there is no
difference in speed in other there are.
My thought would be that its slower and the only gain is that its
easier in a conceptual way to use inheritance, but I don't need a good
design in the first place, I need speed!

I'm most likely not going to use inheritance for that reason but also
because those classes "have" to be differentiated from eachother. By
that I mean they can't just take over eachothers identity. Normal n =
v with v a Vector may not be possible, even used explicit to make
sure, and this kind of concretisation is what one loses by the
abstraction of the superclass no? Or is it my responsability not to
lose the identity of a class into the abstraction of the superclass.

I am not an expert on the subject but I have done some programming
involving 3D and I never found a reason to not use a single vector-class
for vectors, normals, and points. In fact using different types can lead
to inefficiencies if you need to convert between them often (i.e. if a
normal is not a vector you can not calculate the dot-product of it an
another vector and would need to create a vector of it first, sometimes
you want the vector from the origin to a point, again you would have to
create the vector). If you can not tell a normal from a point in your
code it means you use bad names for your variables.
 
D

Daniel T.

For instance take: heavely used classes, lets say Vector(not the
dynamic datatype but a mathematical vector) and Point. They have both
3 class variables x, y and z and some functions they both use.

Now the question is, would subclassing these 2 classes have any
negative effect on the speed of a program that uses these classes very
frequently, i.e. the raytracer I'm building. So completely different
types of classes versus inheritance, which would be faster? Or doesn't
it matter.
My thought would be that its slower and the only gain is that its
easier in a conceptual way to use inheritance, but I don't need a good
design in the first place, I need speed!

I'm most likely not going to use inheritance for that reason but also
because those classes "have" to be differentiated from eachother. By
that I mean they can't just take over eachothers identity. Normal n =
v with v a Vector may not be possible, even used explicit to make
sure, and this kind of concretisation is what one loses by the
abstraction of the superclass no? Or is it my responsability not to
lose the identity of a class into the abstraction of the superclass.

I think I'm starting to get crazy about all the newly gained c++
information that I don't know where to put it all at once =). I'll get
myself some sleep first and maybe tomorow I'll be back on track.

Think of it this way. Inheritance is a way to remove duplicated switch
statements (and "if...else if" chains) from your code. Do you have a
lot of switch statements in your code without using inheritance? If not,
then inheritance probably won't be of any use.
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
For instance take: heavely used classes, lets say Vector(not the
dynamic datatype but a mathematical vector) and Point. They have both
3 class variables x, y and z and some functions they both use.

Now the question is, would subclassing these 2 classes have any
negative effect on the speed of a program that uses these classes very
frequently, i.e. the raytracer I'm building. So completely different
types of classes versus inheritance, which would be faster? Or doesn't
it matter.

Generally speaking, it doesn't matter.
My thought would be that its slower and the only gain is that its
easier in a conceptual way to use inheritance, but I don't need a good
design in the first place, I need speed!

Why would you think it was slower? Inheritance itself happens at
compile-time -- i.e. you've told the compiler to base on struct or class
on another. The type-checking is static so when, for example, you take a
pointer to the base class and assign it the address of a derived class,
the compiler is checking the types only at compile time.

You can cause the code to be slower in a number of ways. First of all,
when you construct an object of a derived class, the compiler basically
walks down the inheritance tree, calling a ctor for class starting from
the and working its way down to the most derived class. As such, if you
have a really deep inheritance tree (generally not advised anyway)
constructing objects can get slower. Likewise with destroying objects.

Calling a virtual function is generally slower than calling a non-
virtual function, but it's generally about the same as going a switch on
the type, and then calling the appropriate function for that type. IOW,
if you do the same thing without inheritance, you're not likely to save
a significant amount of time.
 
M

michael.goossens

I am not an expert on the subject but I have done some programming
involving 3D and I never found a reason to not use a single vector-class
for vectors, normals, and points. In fact using different types can lead
to inefficiencies if you need to convert between them often (i.e. if a
normal is not a vector you can not calculate the dot-product of it an
another vector and would need to create a vector of it first, sometimes
you want the vector from the origin to a point, again you would have to
create the vector). If you can not tell a normal from a point in your
code it means you use bad names for your variables.

Having studied computer graphics - computergraphics 2 : Global
illumination and 3d math I have seen quite some differences between
the different types and the implementations I have seen were always
with different types too. For instance, adding two points to eachother
has no mathematical meaning and should not be possible. If you use
vector to represent points then it is possible to do this summation,
basicly thats wrong.
 
M

michael.goossens

Calling a virtual function is generally slower than calling a non-
virtual function, but it's generally about the same as going a switch on
the type, and then calling the appropriate function for that type. IOW,
if you do the same thing without inheritance, you're not likely to save
a significant amount of time.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Not using switches or if else chains in the first place so my guess
would be to do it without inheritance. Also the design does not have
to be extendable, so no problem there. My first concern is speed,
ofcourse good speed comes from a good design too but in this case
there is no specific gain.

thanks all
 
K

kwikius

On Jan 27, 10:33 am, "(e-mail address removed)"
vector to represent points then it is possible to do this summation,
basicly thats wrong.

Not so. You can find a point p between p1 and p2

p = (p1 + p2)/2;

You can also do this for n points.

Heres a post from Richard Heathfield on comp.programming to do a
bezier:

http://tinyurl.com/yttted


Just to bring this back to C++. At the end a version using my off line
quanta lib, which I may one day get round to reworking and making
publicly available as a new version of my old quan library:

http://sourceforge.net/projects/quan

(N.B) The following wont work with the sourceforge version of quan:

/*
after a post on comp.programming thread font curves from Richard
Heathfield"
*/

#include <quanta/quan/quick_start/length.hpp>
#include <quanta/seq/vector/vector2.hpp>
#include <quanta/seq/vector/vector3.hpp>
#include <quanta/seq/vector/vector4.hpp>
#include <quanta/seq/vector/vector5.hpp>
#include <quanta/seq/out/sequence.hpp>
#include <stdexcept>

namespace impl{

// implement pascal's Triangle
// for various control point combos...
template <int NumCtPoints, int Iter>
struct get_bezier_constant;

// specialisation for 4 control points
template <> struct get_bezier_constant<4,0>
: std::tr1::integral_constant<int,1>{};
template <> struct get_bezier_constant<4,1>
: std::tr1::integral_constant<int,3>{};
template <> struct get_bezier_constant<4,2>
: std::tr1::integral_constant<int,3>{};
template <> struct get_bezier_constant<4,3>
: std::tr1::integral_constant<int,1>{};

// specialisation for 5 control points
template <> struct get_bezier_constant<5,0>
: std::tr1::integral_constant<int,1>{};
template <> struct get_bezier_constant<5,1>
: std::tr1::integral_constant<int,4>{};
template <> struct get_bezier_constant<5,2>
: std::tr1::integral_constant<int,6>{};
template <> struct get_bezier_constant<5,3>
: std::tr1::integral_constant<int,4>{};
template <> struct get_bezier_constant<5,4>
: std::tr1::integral_constant<int,1>{};

// functor to do the calc :

namespace detail{

//internal calc
template <int Iter> struct bezier_impl_eval;
// use compile time recursion to do the calc...
//'bezier_impl_eval<0>' is the compile time
//loop terminating condition
template <>
struct bezier_impl_eval<0>
{
// result type deduction
// CtrlPtSeq is a model of TypeSequence,
// a sequence whose length is known at compiletime
// can be doubles or types representing length
//in physical units etc ( as shown below
template <typename CtrlPtSeq,typename V>
struct apply : quanta::meta::binary_op<
V,
quanta::meta::times,
typename quanta::seq::at said:
>::type // at is equivalenat of s[0]
>{};

// calc function
template <typename CtrlPtSeq,typename V>
typename apply<CtrlPtSeq,V>::type
operator()(CtrlPtSeq const & s,V const & v)const
{
using quanta::seq::num_elements;

return get_bezier_constant<
num_elements said:
* quanta::quan::pow<num_elements<
CtrlPtSeq>::value-1
* quanta::seq::at<0,quanta::fun::as_cref>()(s);
};
};

// non zero iterations
template <int Iter>
struct bezier_impl_eval{
// result type deduction
// recursively compute result type
//from results of previous iterations
template <typename CtrlPtSeq,typename V>
struct apply : quanta::meta::binary_op<
typename bezier_impl_eval<
Iter-1
>::template apply<CtrlPtSeq,V>::type,
quanta::meta::plus,
typename quanta::seq::at<
Iter,quanta::fun::as_cref
>::template apply<CtrlPtSeq>::type
>{};

template <typename CtrlPtSeq,typename V>
typename apply<CtrlPtSeq,V>::type
operator()(CtrlPtSeq const & s,V const & v)const
{
using quanta::seq::num_elements;

return bezier_impl_eval<Iter-1>()(s,v)
// do calc recursively
+ get_bezier_constant<
num_elements said:
* quanta::quan::pow<Iter>(v)
// pow is equivalent std::pow(d,n)
//with compile time bezier_impl_eval on exp
* quanta::quan::pow<num_elements<
CtrlPtSeq
>::value - (Iter + 1)>(1 - v)
* quanta::seq::at<Iter,quanta::fun::as_cref>()(s);
}
};
}
//Holds a sequence of ctrl pts
//auto detects algorith constants from length of sequence
template <typename CtrlPtSeq>
struct get_bezier_impl{
// ctor argument is the control point sequence
// to be evaluated
get_bezier_impl( CtrlPtSeq const & s_in): s(s_in){}
public:
// result of functor is result_type of final eval
template <typename V>
struct apply : detail::bezier_impl_eval<
quanta::seq::num_elements said:
>::template apply<CtrlPtSeq,V>{};

// V is arithmetic
template <typename V>
typename apply<V>::type
operator()(V const & v)const
{
if((v >= V(0)) && (v <= V(1))){
return detail::bezier_impl_eval<
quanta::seq::num_elements said:
>()(s,v);
}
throw std::eek:ut_of_range("bezier pos out of range");
}
private:
CtrlPtSeq const & s;
};
}

// function removes requirement on explicit template param.
template <typename CtrlPtSeq>
inline
impl::get_bezier_impl<CtrlPtSeq>
bez_calculator(CtrlPtSeq const & s)
{
return impl::get_bezier_impl<CtrlPtSeq>(s);
}
// for physical quantities
namespace si = quanta::quan::quick_start;

template <typename CtPts>
void do_bezier_pt( CtPts const & s, double const & p)
{
std::cout << "With ctrl pts :\n";
for_(s,quanta::fun::eek:utput(std::cout,"\n"));
std::cout << "At " << p << " result point = "
<< bez_calculator(s)(p) << "\n\n";
}

int main()
{

try{

// type of sequence of ctrl points for
// 2d points of length in mm.
typedef si::length::mm mm;
typedef quanta::seq::vector2<mm,mm> pt2;
typedef quanta::seq::vector4<pt2,pt2,pt2,pt2> ct_pts2d4;

ct_pts2d4 pts2(
pt2(mm(0),mm(0)),
pt2(mm(0.1),mm(0.1)),
pt2(mm(2),mm(1)),
pt2(mm(3),mm(1))
);

do_bezier_pt(pts2,0);
do_bezier_pt(pts2,0.5);
do_bezier_pt(pts2,1);

// also works for 3d points...
typedef quanta::seq::vector3<mm,mm,mm> pt3;
typedef quanta::seq::vector4<pt3,pt3,pt3,pt3> ct_pts3D4;

ct_pts3D4 pts3(
pt3(mm(0),mm(0),mm(0)),
pt3(mm(0.1),mm(0.1),mm(0.1)),
pt3(mm(2),mm(1),mm(-1)),
pt3(mm(3),mm(1),mm(0))
);

do_bezier_pt(pts3,0.5);

typedef quanta::seq::vector5<pt3,pt3,pt3,pt3,pt3> ct_pts3D5;

ct_pts3D5 pts3a(
pt3(mm(0),mm(0),mm(0)),
pt3(mm(0.1),mm(0.1),mm(0.1)),
pt3(mm(0.2),mm(0.3),mm(0.8)),
pt3(mm(2),mm(1),mm(-1)),
pt3(mm(3),mm(1),mm(0))
);

do_bezier_pt(pts3a,0.1);

}
catch ( std::exception & e){
std::cout << "Caught \"" << e.what() << "\"";
}
}

/* output:

With ctrl pts :
(0 mm,0 mm)
(0.1 mm,0.1 mm)
(2 mm,1 mm)
(3 mm,1 mm)
At 0 result point = (0 mm,0 mm)

With ctrl pts :
(0 mm,0 mm)
(0.1 mm,0.1 mm)
(2 mm,1 mm)
(3 mm,1 mm)
At 0.5 result point = (1.1625 mm,0.5375 mm)

With ctrl pts :
(0 mm,0 mm)
(0.1 mm,0.1 mm)
(2 mm,1 mm)
(3 mm,1 mm)
At 1 result point = (3 mm,1 mm)

With ctrl pts :
(0 mm,0 mm,0 mm)
(0.1 mm,0.1 mm,0.1 mm)
(2 mm,1 mm,-1 mm)
(3 mm,1 mm,0 mm)
At 0.5 result point = (1.1625 mm,0.5375 mm,-0.3375 mm)

With ctrl pts :
(0 mm,0 mm,0 mm)
(0.1 mm,0.1 mm,0.1 mm)
(0.2 mm,0.3 mm,0.8 mm)
(2 mm,1 mm,-1 mm)
(3 mm,1 mm,0 mm)
At 0.1 result point = (0.04638 mm,0.04744 mm,0.06444 mm)

*/
 
J

Jerry Coffin

[ ... ]
Not using switches or if else chains in the first place so my guess
would be to do it without inheritance. Also the design does not have
to be extendable, so no problem there. My first concern is speed,
ofcourse good speed comes from a good design too but in this case
there is no specific gain.

It sounds to me like you had decided on the answer you wanted before you
posted, and rather than looking for real information, you were looking
primarily for justification for what you already wanted.

My post did not say (not was it intended to imply) that lack of switches
or if/else chains was a good reason not to use inheritance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,518
Latest member
RomanGratt

Latest Threads

Top