has_trivial_copy for optimization
I noticed poor performance coping a structure with a bunch of optionals. The reason is the cost of checking if the optionals are set. CPU's hate branching it breaks their pipelining. if(that->a) this->a=*that->a; At the end of the day I just wrote a copy construct which does a memcpy(), since the data types were just POD. It makes me a bit nervous since my code might break with a different impl of opitonal. Then I thought hey wouldn't it be cool if defined a metafunction that specified memcpy/memmove are allowed? It looks like has_trivial_copy<> fits the bill. // Suggested code: namespace boost{ template<typename T> struct has_trivial_copy< boost::optional<T> > : has_trivial_copy<T> {}; }//namespace boost typedef boost::optional<int> OptionalInt; BOOST_STATIC_ASSERT(( has_trivial_copy<OptionalInt>::value )); //fixed thanks to code above struct SomeOptionals{ OptionalInt a,b;}; BOOST_STATIC_ASSERT(( has_trivial_copy<SomeOptionals>::value )); //fails The second test fails. It can't imagine how to make it work without some compiler magic. I wonder if a compiler could use metafunctions to know which optimizations were legal. Similar meta function specializations could be written for boost::variant and boost::fusion::map. I could imagine contains like std::vector using this to do memmove() for example. Chris
On Sep 15, 2010, at 10:28 AM, Hite, Christopher wrote:
I noticed poor performance coping a structure with a bunch of optionals. The reason is the cost of checking if the optionals are set. CPU's hate branching it breaks their pipelining.
if(that->a) this->a=*that->a; At the end of the day I just wrote a copy construct which does a memcpy(), since the data types were just POD. It makes me a bit nervous since my code might break with a different impl of opitonal.
Then I thought hey wouldn't it be cool if defined a metafunction that specified memcpy/memmove are allowed? It looks like has_trivial_copy<> fits the bill.
// Suggested code: namespace boost{
template<typename T> struct has_trivial_copy< boost::optional<T> > : has_trivial_copy<T> {};
}//namespace boost
typedef boost::optional<int> OptionalInt; BOOST_STATIC_ASSERT(( has_trivial_copy<OptionalInt>::value )); //fixed thanks to code above
struct SomeOptionals{ OptionalInt a,b;}; BOOST_STATIC_ASSERT(( has_trivial_copy<SomeOptionals>::value )); //fails
The second test fails.
As well it should. It would be a lie, because the copy c'tor is nontrivial in all cases, even when a trivial copy c'tor would work.
It can't imagine how to make it work without some compiler magic. I wonder if a compiler could use metafunctions to know which optimizations were legal.
It could, when those metafunctions are in std::, and all the type traits will be in std:: for C++0x.
Similar meta function specializations could be written for boost::variant and boost::fusion::map. I could imagine contains like std::vector using this to do memmove() for example.
It looks to me as though the right place to fix this is in boost::optional<T>: it should be specialized so that when T has a trivial copy c'tor, so does boost::optional<T>. I suggest you open a Trac ticket at http://svn.boost.org/trac/boost -- Dave Abrahams BoostPro Computing http://boostpro.com
participants (2)
-
David Abrahams
-
Hite, Christopher