I am having great difficulty in architecting my boost serialization
solution with the Intel compiler.
The problem is this: I need to support text, xml, and binary archive
formats. I allow the user to select which format to save in, by
default using the portable text format. If the user wants greater
speed, they can choose binary, or if they want to visually inspect the
data, they can choose xml. On load, I dynamically detect which
archive is used and call the appropriate load routine (text, xml,
binary).
However, if I include all three archives in the same compilation unit,
the default (text) serialization is slowed down dramatically, with the
runtimes increasing approximately 50% (from 200 to 300 seconds, and
this on a fast 64-bit Opteron box).
I tried breaking things apart, putting my archive includes and
BOOST_CLASS_EXPORT calls into separate compilation units.
I have the following code structure:
class AbstractBase {
virtual void method() = 0;
};
BOOST_IS_ABSTRACT(AbstractBase)
class Derived: public AbstractBase {
virtual void method() {}
};
class A {
Def* def;
template <class Archvie>
void serialize(Archive& ar, const unsigned int version) {
ar & def;
}
};
I break my serialization code into three different files, one for
each type of archive, each of which includes a common file that has
a templated method for loading a serialized file, along with
BOOST_CLASS_EXPORT for the derived class.
Here is the text version:
#include
#include "Serialization.hh"
A* BoostTextLoader::load() {
return Serialization::load(fileName);
}
#include
BOOST_CLASS_EXPORT(Derived)
Here is the binary:
#include
#include "Serialization.hh"
A* BoostTextLoader::load() {
return Serialization::load(fileName);
}
#include
BOOST_CLASS_EXPORT(Derived)
and a similar one for XML. The Serialization.hh is roughly this:
template<typename Archive>
struct FanSerialization {
static A* load(const std::string& filename) {
A* a = 0;
stream ifs(filename);
Archive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(a);
return a;
}
}
When I compile and try to link a test program, I get errors saying
"multiple definition of
`boost::archive::detail::guid_initializer<Derived>::instance'" and so
on. So, I try removing the BOOST_CLASS export from the binary and XML
code modules, leaving it in the text version. Compile and link are
now good. The text archive performance is back down to 200 seconds.
When I try to serialize binary (or xml) archives, I get.
/boost-1_33_1/boost/archive/detail/oserializer.hpp:418: static void boost::archive::detail::save_pointer_type::polymorphic<T>::save(Archive &, const T &, const boost::archive::detail::basic_pointer_oserializer *) [with T = AbstractBase, Archive = boost::archive::xml_oarchive, TPtr = AbstractBase*]: Assertion `0L != bpos_ptr' failed.
The code that is failing is from the assert below (oserializer.hpp):
// sice true_type is valid, and this only gets made if the
// pointer oserializer object has been created, this should never
// fail
bpos_ptr = archive_pointer_oserializer<Archive>::find(* true_type);
assert(NULL != bpos_ptr);
if(NULL == bpos_ptr)
boost::throw_exception(
archive_exception(archive_exception::unregistered_class)
);
ar.save_pointer(vp, bpos_ptr);
So, needless to say, I'm a bit confused by what is going on.
Is there any way at all to fix this? I have run a profiler on the
Intel code and it simply seems to be "doing more" than the non-Intel
version (more comparison operators, chiefly).
Could there be any way to manually instantiate things, or substitute
the containers boost uses for look-ups at run-time with different,
separate ones?
Thanks.
Bill