Sander boer's change for multithreading

1. Added multithread for create element
2. Added support function in IfcConvert.cpp for multithreading at bottom
This commit is contained in:
You Yue
2019-07-02 12:10:08 +02:00
parent 869cc25061
commit a286598e55
+136 -48
View File
@@ -787,61 +787,61 @@ int main(int argc, char** argv) {
Logger::Status("Creating geometry...");
}
// The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next()
// wrap an iterator of all geometrical products in the Ifc file.
// IfcGeom::Iterator::get() returns an IfcGeom::TriangulationElement or
// -BRepElement pointer, based on current settings. (see IfcGeomIterator.h
// for definition) IfcGeom::Iterator::next() is used to poll whether more
// geometrical entities are available. None of these functions throw
// exceptions, neither for parsing errors or geometrical errors. Upon
// calling next() the entity to be returned has already been processed, a
// non-null return value guarantees that a successfully processed product is
// available.
size_t num_created = 0;
/// =============== Sanders approach for multiple threading ============================
for (int j = 0; j < (int)IfcproductRepresentations.size(); j++)
{
IfcproductRepresentation &r = IfcproductRepresentations[j];
create_element(settings, r, kernel2x3);
do {
IfcGeom::Element<real_t> *geom_object = context_iterator.get();
if (is_tesselated)
if (threadpool.size() < concurrency)
{
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom_object));
std::future<void> fu = std::async(std::launch::async, create_element, std::ref(settings), std::ref(r), std::ref(kernel2x3));
threadpool.emplace_back(std::move(fu));
j++;
}
else
{
serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
}
bool waiting = true;
while (waiting)
{
for (int i = 0; i < (int)threadpool.size(); i++)
{
cout << "Thread pool size: " << threadpool.size();
std::future<void> &fu = threadpool[i];
std::future_status status;
status = fu.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready)
{
fu.get();
threadpool.erase(threadpool.begin() + i);
waiting = false;
} // if
} // for
} // while
} //else
}
if (!no_progress) {
if (quiet) {
const int progress = context_iterator.progress();
for (; old_progress < progress; ++old_progress) {
std::cout << ".";
if (stderr_progress)
std::cerr << ".";
}
std::cout << std::flush;
if (stderr_progress)
std::cerr << std::flush;
} else {
const int progress = context_iterator.progress() / 2;
if (old_progress != progress) Logger::ProgressBar(progress);
old_progress = progress;
}
}
} while (++num_created, context_iterator.next());
if (!no_progress && quiet) {
for (; old_progress < 100; ++old_progress) {
std::cout << ".";
if (stderr_progress)
std::cerr << ".";
// Serializer
for (int j = 0; j < (int)IfcproductRepresentations.size(); j++)
{
IfcproductRepresentation *rep = &IfcproductRepresentations[j];
//write_element(serializer, rep, is_tesselated);
cout_ << "writing to file, element #: " << rep->index << "\n";
IfcGeom::Element<real_t> *geom_object = rep->element;
if (geom_object == nullptr)
{
cout_ << "skipped" << std::endl;
continue;
}
std::cout << std::flush;
if (stderr_progress)
std::cerr << std::flush;
} else {
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
" objects) ");
if (is_tesselated)
{
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t> *>(geom_object));
}
else
{
serializer->write(static_cast<const IfcGeom::BRepElement<real_t> *>(geom_object));
}
}
serializer->finalize();
@@ -1348,3 +1348,91 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////// ***** Added for multithreading ****** /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
bool reuse_ok_(SerializerSettings settings, const IfcSchema::IfcProduct::list::ptr &products, IfcGeom::Kernel kernel)
{
IfcGeom::KernelIfc2x3 kernel2x3;
if(settings.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS))
{
return false;
}
std::set<const IfcSchema::IfcMaterial *> associated_single_materials;
for(IfcSchema::IfcProduct::list::it it = products->begin(); it != products->end(); ++it)
{
IfcSchema::IfcProduct *product = *it;
if(!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) &&
kernel2x3.find_openings(product)->size())
{
return false;
}
if (settings.get(IfcGeom::IteratorSettings::APPLY_LAYERSETS))
{
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
for (IfcSchema::IfcRelAssociates::list::it jt = associations->begin(); jt != associations->end(); ++jt)
{
IfcSchema::IfcRelAssociatesMaterial *assoc = (*jt)->as<IfcSchema::IfcRelAssociatesMaterial>();
if (assoc)
{
//if (assoc->RelatingMaterial()->is(IfcSchema::IfcMaterialLayerSetUsage))
if (assoc->RelatingMaterial()->declaration().is(IfcSchema::IfcMaterialLayerSetUsage::Class()))
{
return false;
}
}
}
}
associated_single_materials.insert(kernel2x3.get_single_material_association(product));
if (associated_single_materials.size() > 1)
{
return false;
}
}
return associated_single_materials.size() == 1;
}
void write_element(boost::shared_ptr<GeometrySerializer> serializer, IfcproductRepresentation *rep, bool is_tesselated)
{
IfcGeom::Element<real_t> *geom_object = rep->element;
if (is_tesselated)
{
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t> *>(geom_object));
}
else
{
serializer->write(static_cast<const IfcGeom::BRepElement<real_t> *>(geom_object));
}
}
void create_element(SerializerSettings &settings, IfcproductRepresentation &rep, IfcGeom::KernelIfc2x3& kernel2x3)
{
////////////////////////////////////////////////////////////
// is kernel thread-safe ?
// @tfk: no, it's not, my advise would be to boot one
// kernel instance per thread.
////////////////////////////////////////////////////////////
Logger::Status("processing item #: " + std::to_string(rep.index));
IfcSchema::IfcRepresentation *representation = rep.representation;
IfcSchema::IfcProduct *product = rep.product;
// IfcGeom::BRepElement<real_t> *element;
//rep.element = kernel2x3.create_brep_for_representation_and_product<real_t, real_t>(settings, representation, product);
rep.brep = kernel2x3.create_brep_for_representation_and_product<real_t, real_t>(settings, representation, product);
rep.element = rep.brep ? new IfcGeom::TriangulationElement<double>(*rep.brep) : nullptr;
// if(geometry_reuse_ok_for_current_representation_)
// {
// // element =
// kernel.create_brep_for_processed_representation(settings,
// representation,
// // product,
// // current_shape_model);
// }
return;
}