При сравнении двух вариантов указателей — классического и Shared_ptr — я был удивлен значительным увеличением скорости работы программы. Для тестирования 2D-алгоритма инкрементной вставки Делоне использовался.
Время работы версий Shared_ptr примерно в 10 раз дольше. Это вызвано настройками компилятора или реализация Shared_ptr в C++ 0x00 такая медленная?
Профилировщик VS2010: для необработанных указателей около 60% времени тратится на эвристический поиск треугольник, содержащий вставленную точку (это нормально, это общеизвестный факт). Но для версии Shared_ptr около 58% времени тратится на использование Shared_ptr.reset() и только 10% используется для эвристического поиска.
Существует значительное улучшение, но версия с общим_птром по-прежнему в 4 раза медленнее, чем версия с необработанным указателем. Боюсь, что скорость работы программы существенно увеличить не получится.
При сравнении двух вариантов указателей — классического и Shared_ptr — я был удивлен значительным увеличением скорости работы программы. Для тестирования 2D-алгоритма инкрементной вставки Делоне использовался.
Время работы версий Shared_ptr примерно в 10 раз дольше. Это вызвано настройками компилятора или реализация Shared_ptr в C++ 0x00 такая медленная?
Профилировщик VS2010: для необработанных указателей около 60% времени тратится на эвристический поиск треугольник, содержащий вставленную точку (это нормально, это общеизвестный факт). Но для версии Shared_ptr около 58% времени тратится на использование Shared_ptr.reset() и только 10% используется для эвристического поиска.
// Legalize triangle T3 if ( e3->getTwinEdge() != NULL ) { legalizeTriangle ( p, e3 ); } }
// Point lies on the edge of the triangle else if ( status == 2 ) { // Find adjacent triangle HalfEdge *e4 = ( *e1 )->getTwinEdge(); HalfEdge *e5 = e4->getNextEdge(); HalfEdge *e6 = e5->getNextEdge();
// Create first new triangle T1, twin edges set after creation e21 = new HalfEdge ( p, e3, NULL ); ( *e1 )->setNextEdge ( e21 );
// Create second new triangle T2, OK e12 = new HalfEdge ( p, e2, e4 ); e32 = new HalfEdge ( e3->getPoint(), e12, e21 ); e2->setNextEdge ( e32 );
// Create third new triangle T3, twin edges set after creation e53 = new HalfEdge ( p, e6, NULL ); e4->setNextEdge ( e53 );
// Create fourth new triangle T4, OK e44 = new HalfEdge ( p, e5, *e1 ); e63 = new HalfEdge ( e6->getPoint(), e44, e53 ); e5->setNextEdge ( e63 );
// Set twin edges in T1, T3 e21->setTwinEdge ( e32 ); ( *e1 )->setTwinEdge ( e44 ); e53->setTwinEdge ( e63 ); e4->setTwinEdge ( e12 );
// Add new edges into list half_edges_dt->push_back ( e21 ); half_edges_dt->push_back ( e12 ); half_edges_dt->push_back ( e32 ); half_edges_dt->push_back ( e53 ); half_edges_dt->push_back ( e63 ); half_edges_dt->push_back ( e44 );
//Throw exception throw ErrorBadAlloc ( "EErrorBadAlloc: ", "Delaunay triangulation: Can not create new triangles for inserted point p." ); }
//Throw exception catch ( ErrorMathZeroDevision &e ) { //Free memory if ( e31 != NULL ) delete e31; if ( e21 != NULL ) delete e21; if ( e12 != NULL ) delete e12; if ( e32 != NULL ) delete e32; if ( e23 != NULL ) delete e23; if ( e13 != NULL ) delete e13; if ( e53 != NULL ) delete e53; if ( e44 != NULL ) delete e44; if ( e63 != NULL ) delete e63;
//Throw exception throw ErrorBadAlloc ( "EErrorMathZeroDevision: ", "Delaunay triangulation: Can not create new triangles for inserted point p." ); } } [/code]
Тестирование кода с помощью Shared_ptr:
Код был переписан без какой-либо оптимизации...
[code]void DT2D::DTInsertPoint ( std::shared_ptr p, std::shared_ptr *e1, HalfEdgesList * half_edges_dt ) { // One step of the Delaunay triangulation, incremental insertion by de Berg (2001) short status = -1;
try { // Test, if point lies inside triangle *e1 = LawsonOrientedWalk::findTriangleWalk ( p, &status, *e1, 0 );
if ( e1 != NULL ) { // Edges inside triangle lies the point std::shared_ptr e2((*e1 )->getNextEdge()); std::shared_ptr e3(e2->getNextEdge());
// Point lies inside the triangle if ( status == 1 ) { // Create first new triangle T1, twin edges set after creation e31.reset( new HalfEdge ( p, *e1, NULL )); e21.reset( new HalfEdge ( e2->getPoint(), e31, NULL )); ( *e1 )->setNextEdge ( e21 );
// Create second new triangle T2, twin edges set after creation e12.reset( new HalfEdge ( p, e2, NULL )); e32.reset( new HalfEdge ( e3->getPoint(), e12, NULL )); e2->setNextEdge ( e32 );
// Create third new triangle T3, twin edges set after creation e23.reset( new HalfEdge ( p, e3, NULL )); e13.reset( new HalfEdge ( ( *e1 )->getPoint(), e23, NULL )); e3->setNextEdge ( e13 );
// Legalize triangle T3 if ( e3->getTwinEdge() != NULL ) { legalizeTriangle ( p, e3 ); } }
// Point lies on the edge of the triangle else if ( status == 2 ) { // Find adjacent triangle std::shared_ptr e4 = ( *e1 )->getTwinEdge(); std::shared_ptr e5 = e4->getNextEdge(); std::shared_ptr e6 = e5->getNextEdge();
// Create first new triangle T1, twin edges set after creation e21.reset(new HalfEdge ( p, e3, NULL )); ( *e1 )->setNextEdge ( e21 );
// Create second new triangle T2, OK e12.reset(new HalfEdge ( p, e2, e4 )); e32.reset(new HalfEdge ( e3->getPoint(), e12, e21 )); e2->setNextEdge ( e32 );
// Create third new triangle T3, twin edges set after creation e53.reset(new HalfEdge ( p, e6, NULL )); e4->setNextEdge ( e53 );
Существует значительное улучшение, но версия с общим_птром по-прежнему в 4 раза медленнее, чем версия с необработанным указателем. Боюсь, что скорость работы программы существенно увеличить не получится.
Вот код
Это функция, которая вставляет узел после указанного местоположения. Здесь у нас есть узел temp и ptr. Узел Temp будет хранить узел, после которого необходимо вставить новый узел, а узел ptr хранит данные нового узла.
здесь после...
Вот код
Это функция, которая вставляет узел после указанного местоположения. Здесь у нас есть узел temp и ptr. Узел Temp будет хранить узел, после которого необходимо вставить новый узел, а узел ptr хранит данные нового узла.
здесь после...
При сравнении двух вариантов указателей — классического и Shared_ptr — я был удивлен значительным увеличением скорости работы программы. Для тестирования 2D-алгоритма инкрементальной вставки Делоне использовался.
У меня есть реализация:
Получение heap-use-after-free с трассировкой, указывающей на
#0 0x102b82868 in int std::__1::__cxx_atomic_fetch_sub (std::__1::__cxx_atomic_base_impl*, int, std::__1::memory_order) cxx_atomic_impl.h:464
Я знаю, что когда вы спросите о «лучших практиках», вы получите ответы от «такого не существует» до «если вы не можете им следовать, вы ошибаетесь», поэтому я могу получить не самые лучшие ответы. Однако из-за этого...
Я зацикливаюсь на лучшем...