Почему CGAL значительно медленнее под Windows? - PullRequest
0 голосов
/ 19 сентября 2019

Версия Windows для моего программного обеспечения в 2-3 раза медленнее, чем для Linux.Чтобы отладить это и продемонстрировать проблему, я создал три простых тестовых функции:

  • benchDouble () выполняет вычисления двойной точности
  • benchCgalSimple () вычисляет пересечение двух линий безвысокоточные числа
  • benchCgalGmpq () вычисляет скользящее пересечение двух линий так, что требуются числа GMPQ

Я настроил циклы так, что на моем эталонном компьютере каждая функция принимает ~5 секунд:

i7-6800K CPU @ 3,40 ГГц, Linux x64

Time consumption: 
* START [Double precision test]...
* STOP [Double precision test]:5.21951 s

* START [CGAL simple]...
* STOP [CGAL simple]:4.98616 s

* START [CGAL GMPQ]...
* STOP [CGAL GMPQ]:4.93984 s

Factors:
  CgalSimple / Double = 0.955293
  CgalGmpq / Double = 0.946417

Теперь давайте проверим это под Windows:

i7-6800K CPU @ 3,40 ГГц, Win10в Virtualbox

* START [Double precision test]...
* STOP [Double precision test]:4.82424 s

* START [CGAL simple]...
* STOP [CGAL simple]:9.251 s

* START [CGAL GMPQ]...
* STOP [CGAL GMPQ]:12.723 s

Factors:
  CgalSimple / Double = 1.91761
  CgalGmpq / Double = 2.63732

... Virtualbox и другой компилятор не оказывают существенного эффекта, поскольку первый тест занимает еще около 5 секунд.Но потребление времени для функций CGAL в 2,6 раза выше.

Xeon E5645 @ 2,4 ГГц, Win10 direct (без виртуальной машины)

Time consumption:
* START [Double precision test]...
* STOP [Double precision test]:10.1158 s

* START [CGAL simple]...
* STOP [CGAL simple]:15.8708 s

* START [CGAL GMPQ]...
* STOP [CGAL GMPQ]:20.1676 s

Factors:
  CgalSimple / Double = 1.5689
  CgalGmpq / Double = 1.99366

... на старом сервере Xeon результат аналогичен, функции CGAL работают в 2 раза медленнее, чемдвойной тест точности.

Условия компиляции:

Я использовал CGAL-4.13.1.CGAL и эталонная программа были скомпилированы под Win10 с VS2015.Я уже пробовал различные варианты оптимизации.Последний тест был выполнен с помощью команды:

(Редактировать: настройка оптимизации изменена на O2)

/ MP / GS- / TP / GL / W3 / Zc: wchar_t / I "c: \ benchCgal "/ I" c: \ benchCgal \ 3rdParty_64 \ boost_1_68_0 "/I"c:\local\CGAL-4.13.1" /I"c:\local\CGAL-4.13.1\build\include "/Я "c: \ local \ CGAL-4.13.1 \ build \ include \ CGAL" /I"C:\local\CGAL-4.13.1\auxiliary\gmp\include "/ I" C: \ benchCgal \ winBuild2 "/Я "C: \ local \ CGAL-4.13.1 \ lib \ cmake \ CGAL ...... \ include" / Gm- / O2 / Ob2 /Fd"benchCgal.dir\Release\vc140.pdb "/ Zc:inline / fp: точный / D "WIN32" / D "_WINDOWS" / D "NDEBUG" / D "BOOST_ALL_DYN_LINK" / D "CMAKE_INTDIR = \" Release \ "" / D "_MBCS" / errorReport: подсказка / GT / WX-/ Zc: forScope / GR / Gd / Oy / Oi / MD / Fa "Release /" / EHsc / Fo "benchCgal.dir \ Release \" / Ot /Fp"benchCgal.dir\Release\benchCgal.pch "

Тестовая программа:

#include <stdio.h>
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <math.h>
#include <chrono>
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
typedef K::FT dbl;
typedef K::Line_3 Line_3;
typedef K::Point_3 Point_3;
typedef std::chrono::time_point<std::chrono::high_resolution_clock> TimePoint;
typedef std::chrono::duration<double> Duration;

using namespace std;

double stopWatch(const std::string& s)
{
        static bool bRunning(false);
        static TimePoint start;
        if(bRunning)
        {
                Duration d(std::chrono::high_resolution_clock::now()-start);
                cout<<"* STOP ["<<s<<"]:"<<d.count()<<" s"<<endl<<endl;
                bRunning=false;
                return d.count();
        }
        else
        {
                cout<<"* START ["<<s<<"]..."<<endl;
                bRunning=true;
                start=std::chrono::high_resolution_clock::now();
                return -1;
        }
}

double sum(1.0);
void benchDouble()
{
    for(double i=0;i<185;i+=1.0)
    {
            for(double j=0;j<1000;j+=1.0)
            {
                    for(double k=0;k<1000;k+=1.0)
                    {
                            sum+=sqrt(i*i+j*j+k*k)*sqrt(i*k+j*k+i*j);
                            sum+=cos(.00314*k)+sin(.00314*k);
                            sum/=(i+k+j*j+1);
                    }
            }
    }
}

double benchCgalSimple()
{
    double sum(0);
    for(int i=0;i<3731000;++i)
    {
        Point_3 p0(0,0,0);
        Point_3 p1(2,0,0);
        Point_3 p2(1,1,0);
        Point_3 p3(1,-1,0);
        Line_3 line0(p0,p1);
        Line_3 line1(p2,p3);
        if(!do_intersect(line0,line1)) continue;
        CGAL::Object obj(CGAL::intersection(line0,line1));
        Point_3 isp;
        bool bOK(CGAL::assign(isp,obj));
        if(bOK) sum+=to_double(isp.x()+isp.y()+isp.z());
    }
    return sum;
}

double benchCgalGmpq()
{
    double sum(0);
    for(int i=0;i<96198;++i)
    {
        Point_3 p0(0,0,0);
        Point_3 p1(1,DBL_MIN,DBL_MIN);
        Point_3 p2(2,DBL_MIN,DBL_MIN);
        Point_3 p3(3,0,0);
        Line_3 line0(p0,p1);
        Line_3 line1(p2,p3);
        if(!do_intersect(line0,line1)) continue;
        CGAL::Object obj(CGAL::intersection(line0,line1));
        Point_3 isp;
        bool bOK(CGAL::assign(isp,obj));
        if(bOK) sum+=to_double(isp.x().exact()+isp.y().exact()+isp.z().exact());
    }
    return sum;
}

int main()
{
    cout<<"Benchmarks started..."<<endl<<endl;

    cout<<"Time consumption: "<<endl;
    stopWatch("Double precision test");
    benchDouble();
    double timeDouble=stopWatch("Double precision test");

    stopWatch("CGAL simple");
    benchCgalSimple();
    double timeCgalSimple=stopWatch("CGAL simple");

    stopWatch("CGAL GMPQ");
    benchCgalGmpq();
    double timeCgalGmpq=stopWatch("CGAL GMPQ");

    cout<<"Factors:"<<endl;
    cout<<"  CgalSimple / Double = "<<timeCgalSimple/timeDouble<<endl;
    cout<<"  CgalGmpq / Double = "<<timeCgalGmpq/timeDouble<<endl;
}

Примечание: Вышеприведенный тест вычисляет не только абсолютные затраты времени, но и два фактора, которые сравнивают функции CGAL с функцией не-CGAL.Эти факторы составляют около 1,0 в Linux и до 2,6 в Windows.Различные типы ЦП (или в одном случае использование ВМ) влияют на всю программу, и поэтому факторы все еще значимы.

(правка):

Новые контрольные данные

ВОбсуждение ниже эталонного метода обсуждалось потому, что Windows работала на виртуальной машине.Теперь коллега запустил его для меня на своей машине с двойной загрузкой, i7-7700 CPU @ 3,6 ГГц.

WINDOWS:

* START [Double precision test]...
* STOP [Double precision test]:3.13713 s 
 
* START [CGAL simple]...
* STOP [CGAL simple]:7.66628 s (+86 % compared to linux)
 
* START [CGAL GMPQ]...
* STOP [CGAL GMPQ]:10.6407 s (+78% compared to linux)

Linux:

* START [Double precision test]...
* STOP [Double precision test]:4.41382 s
 
* START [CGAL simple]...
* STOP [CGAL simple]:4.10052 s
 
* START [CGAL GMPQ]...
* STOP [CGAL GMPQ]:5.97985 s
...