//#undef CGAL_LINKED_WITH_TBB #include #include #include #ifdef CGAL_LINKED_WITH_TBB # include # include # include # include #endif //#define TEST_CCSS #include #include struct Sequential_with_forward_access_tag : public CGAL::Sequential_tag {}; struct Sequential_with_random_access_tag : public CGAL::Sequential_tag {}; struct Parallel_for_tag : public CGAL::Parallel_tag {}; struct Parallel_do_tag : public CGAL::Parallel_tag {}; struct Truc { Truc(int v = 0) : value(v), /*value2(v), */p(NULL) {} void * for_compact_container() const { return p; } void for_compact_container(void *ptr) { p = ptr; } int value; int value2; void * p; }; inline void compute_the_thing(int &thing) { thing = static_cast(10.*sqrt(0.3 + thing*thing/1.5)/2.6); //thing = 10*thing; } inline void compute_the_thing(Truc &thing) { thing.value2=thing.value; compute_the_thing(thing.value2); } #ifdef CGAL_LINKED_WITH_TBB // For parallel_for template class Change_array_functor { public: Change_array_functor(Array_t &v) : m_v(v) {} Change_array_functor(const Change_array_functor &caf) : m_v(caf.m_v) {} void operator() (const tbb::blocked_range& r) const { for(size_t i = r.begin(); i != r.end(); i++ ) if (m_v.is_used(i)) compute_the_thing(m_v[i]); } private: Array_t &m_v; }; // For parallel_for // Specialization for std::vector template <> class Change_array_functor > { public: Change_array_functor(std::vector &v) : m_v(v) {} Change_array_functor(const Change_array_functor &caf) : m_v(caf.m_v) {} void operator() (const tbb::blocked_range& r) const { for(size_t i = r.begin(); i != r.end(); i++ ) compute_the_thing(m_v[i]); } private: std::vector &m_v; }; // For parallel_do template class Change_array_functor_2 { public: void operator() (typename Array_t::value_type& truc) const { compute_the_thing(truc); } }; // Parallel_for // For vector only double change_array(std::vector &v, Parallel_for_tag) { std::cout << "[Parallel] Using a tbb::parallel_for loop..."; CGAL::Real_timer t; t.start(); tbb::parallel_for( tbb::blocked_range(0, v.size()), Change_array_functor >(v) ); t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } // Parallel_for // For Compact_container only template double change_array(Array_t &v, Parallel_for_tag) { std::cout << "[Parallel] Using a tbb::parallel_for loop..."; CGAL::Real_timer t; t.start(); tbb::parallel_for( tbb::blocked_range(0, v.capacity()), Change_array_functor(v) ); t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } // Parallel_do // For vector and Compact_container template double change_array(Array_t &v, Parallel_do_tag) { std::cout << "[Parallel] Using a tbb::parallel_do loop..."; CGAL::Real_timer t; t.start(); tbb::parallel_do( v.begin(), v.end(), Change_array_functor_2()); t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } #endif // Forward access // For vector & Compact_container template double change_array(Array_t &v, Sequential_with_forward_access_tag) { std::cout << "[Sequential] Using a sequential for loop (forward access)..."; CGAL::Real_timer t; t.start(); typename Array_t::iterator it = v.begin(), it_end = v.end(); for ( ; it != it_end ; ++it) compute_the_thing(*it); t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } // Random access // For vector only double change_array(std::vector &v, Sequential_with_random_access_tag) { std::cout << "[Sequential] Using a sequential for loop (random access)..."; CGAL::Real_timer t; t.start(); std::vector::iterator it = v.begin(), it_end = v.end(); for (int i = 0 ; i < v.size() ; ++i) compute_the_thing(v[i]); t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } // Random access // For Compact_container (use of "is_used") template double change_array(Array_t &v, Sequential_with_random_access_tag) { std::cout << "[Sequential] Using a sequential for loop (random access)..."; CGAL::Real_timer t; t.start(); for (int i = 0 ; i < v.capacity() ; ++i) { if (v.is_used(i)) compute_the_thing(v[i]); } t.stop(); std::cout << " done in " << t.time() << " seconds." << std::endl; return t.time(); } template void benchmark(Array_t &v) { std::cout << "* Sequential algorithm (random access) => "; double seq_time_random = change_array(v, Sequential_with_random_access_tag()); std::cout << "* Parallel_for algorithm => "; double parallel_for_time = change_array(v, Parallel_for_tag()); std::cout << "Speed-up parallel_for (operator[]) = " << seq_time_random/parallel_for_time << std::endl << std::endl; std::cout << "* Sequential algorithm (forward access) => "; double seq_time_fw = change_array(v, Sequential_with_forward_access_tag()); std::cout << "* Parallel_do algorithm => "; double parallel_do_time = change_array(v, Parallel_do_tag()); std::cout << "Speed-up parallel_do (iterators) = " << seq_time_fw/parallel_do_time << std::endl << std::endl; } int main() { #ifdef _DEBUG const int NUM_THINGS = 1000; #else const int NUM_THINGS = 10000000; #endif std::cout << std::endl << "*** VECTOR ***" << std::endl; CGAL::Real_timer t; t.start(); std::vector v; for (int i = 0 ; i < NUM_THINGS ; ++i) v.push_back(i); t.stop(); std::cout << "vector created in " << t.time() << " seconds." << std::endl; benchmark(v); std::cout << std::endl << "*** CC ***" << std::endl; t.reset(); t.start(); CGAL::Compact_container v2; for (int i = 0 ; i < NUM_THINGS ; ++i) v2.emplace(i); t.stop(); std::cout << "Compact_container created in " << t.time() << " seconds. Capacity = " << v2.capacity() << std::endl; benchmark(v2); std::cout << std::endl << "*** CC ***" << std::endl; t.reset(); t.start(); CGAL::Compact_container > v3; for (int i = 0 ; i < NUM_THINGS ; ++i) v3.emplace(i); t.stop(); std::cout << "Compact_container created in " << t.time() << " seconds. Capacity = " << v3.capacity() << std::endl; benchmark(v3); return 0; }