Boost logo

Boost Users :

Subject: Re: [Boost-users] compilation problem and a coupleofboost::variantquestions
From: Petros (pmamales_at_[hidden])
Date: 2012-07-12 08:10:51


Hi Jeff,
Thank you for your careful response.
I am now increasingly convinced that boost::variant was the wrong choice for my problem at hand.
Dispatching to “which()” with every call is unacceptable performance-wise.
I am not familiar with boost::function, started looking into it last night.
O/wise, I can always typedef inside each generator class the outcome to, say, result_type and then have an algebra on the result_type-s.
Thank you very much for all your help and time,
Petros

From: Jeffrey Lee Hellrung, Jr.
Sent: Wednesday, July 11, 2012 8:23 PM
To: boost-users_at_[hidden]
Subject: Re: [Boost-users] compilation problem and a coupleofboost::variantquestions

On Wed, Jul 11, 2012 at 4:38 PM, Petros <pmamales_at_[hidden]> wrote:
[...]

>> You mean the first type in the sequence of value types that is convertible from the argument? That's possible, but I don't believe boost::variant presently attempts to do that. You can always try!
  Or, maybe can’t ) (I really have a user’s knowledge/attitude to variant).

I meant, literally, you can just try it:

boost::variant< int, int > x(0);

[...]

>> Hmmm...then why are you using variant?
  Because I need a single type as an output from my various templates.
  Say you are solving a PDE. And your various PDE classes contain (coefficient) functions of all kinds ( contstants, zeros etc.) Then I want to have a unique type
  as an output. A variant seemed like a good idea. The type of the function is known at compile time. I just don’t want to carry around O(N^2) types where N the dimensionality of the PDE
  - and this is just for the cross terms.

Hmmm...okay; have you consider boost::function?
 
>>Well, variant essentially erases the type of the object it's constructed with, so you're effectively using runtime polymorphism (though of a more controlled nature than boost::any or virtual functions). I don't know enough
  about the particulars of your application based on your description above to know if that's appropriate.
  Here is a problem to understand what I am thinking of (only for info purposes, no purpose of cluttering you):
  Say, I have a vector Monte-Carlo engine that advances like
  V(t_dt) = m*dt * sigma*Fi*zeta*random
  where now m, sigma, Fi, zeta can be zero or one and have various classes that produce them. I want to have a single class for the advancement (actually there are various different classes dependent on the numerical method).
  Now, I can use expression templates for them, but there are significant gains if I know that certain type are fixed (say, m = 0 and/or zeta = 1 ).
  This is why I want to ba able to have these functions in a controlled manner (they are only a few of those, so a variant seems natutral.
  The same with a PDE example.

It sounds like the optimizations you're looking for are pretty application specific. For example, if you perform runtime checks on whether some of your factors are constant or zero to avoid recomputing some factors or avoid computing other factors altogether, you *might* get some performance gains in some situations but you'll probably lose performance in other situations. It depends on whether the branching for those checks hurts you, what the relative cost is of computing the more expensive factors, etc.

I might suggest delaying the type erasure as much as possible. For example, set up your interface such that you package the entire expression m * dt * sigma * Fi * zeta * random into a type-erased object (like boost::function) and use the static types for the individual factors. I don't know if that's possible or reasonable for your use case but it might give you some ideas.

  What I really need is some variant type that encapsulates what I described above. The number of calls to the subscript operator is going to be in the millions. (btw this is what I call opimized)

Every call to the subscript operator is going to have to dispatch through the which() index to determine the underlying dynamic type of the variant. This is likely going to be significantly slower than indexing a std::vector. The only way to be sure is to benchmark it yourself.

[...]

  PS: No offense to anyone, but the documentation is a bit obscure. I think there would be a certain benefit, if in the documentation there was some info on implementation issues, to allow people
  to make more educated decisions.

That's fair; it's likely like that since the implementation is liable to change, or vary greatly across various compilers depending on which compilers perform best with which implementation. Ultimately, if you're to the point where you need to know the implementation of boost::variant for something, you'd probably have to look at the source code anyway to be sure.
 
  Maybe it is my fault, but after having spent some time with it, I still do not know what is contained in the data structure ( copies, references/pointers-to-external objects, who knows),

A boost::variant just "holds" an object of one of its value types. It's the same idea as a union, e.g., a boost::variant< int, double > is basically the same as

struct V
{
    union { int i; double d; } u;
    int which;
};

Or maybe instead of an index to discriminate what's in the union, a pointer is used; that's implementation-dependent.

  what are the guarantees of compile-time variant etc.

Actually the guarantees of boost::variant are very well documented and (I thought) a strong point of the documentation...

- Jeff

--------------------------------------------------------------------------------
_______________________________________________
Boost-users mailing list
Boost-users_at_[hidden]
http://lists.boost.org/mailman/listinfo.cgi/boost-users



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net