OpenMP работает медленнее чем последовательный для DIPlib - PullRequest
1 голос
/ 24 января 2020

Я использую findshift.cpp из https://github.com/DIPlib/diplib/blob/master/src/analysis/findshift.cpp в коде ниже:

int main()
{
    std::vector<double>x1 = {0,0,0,0,0 };
    std::vector<double>y1 = { 0,0,0,0,0 };

    double* xarr = &x1[0];
    double* yarr = &y1[0];
    double res=0.0;

    std::string outputDir = "C:/me/openmp";

    double t = -omp_get_wtime();
    for (int k = 0; k < 600; k++) {
        for (int j = 0; j < 100; j++) {
            res = runFindShift(xarr, yarr, x1.size(), x1, y1);
        }
        std::string str1 = outputDir + "/" + "serial" + "k" + std::to_string(k) + ".csv";
        const char *str = str1.c_str();
        std::ofstream out(str);
        out << res;
        out.close();
        std::cout << "k: " << k << ", res: " << res << std::endl;
    }
    t += omp_get_wtime();

    res = 0.0;
    double t2 = -omp_get_wtime();
    #pragma omp for
    for (int k = 0; k < 600; k++) {
        for (int j = 0; j < 100; j++) {
            res = runFindShift(xarr, yarr, x1.size(), x1, y1);
        }
        std::string str1 = outputDir + "/" + "ompFor" + "k" + std::to_string(k) + ".csv";
        const char *str = str1.c_str();
        std::ofstream out(str);
        out << res;
        out.close();
        std::cout << "k: " << k << ", res: " << res << std::endl;
    }
    t2 += omp_get_wtime();

    res = 0.0;
    double t3 = -omp_get_wtime();
    #pragma omp parallel for
    for (int k = 0; k < 600; k++) {
        for (int j = 0; j < 100; j++) {
            res = runFindShift(xarr, yarr, x1.size(), x1, y1);
        }
        std::string str1 = outputDir + "/" + "ompParFor" + "k" + std::to_string(k) + ".csv";
        const char *str = str1.c_str();
        std::ofstream out(str);
        out << res;
        out.close();
        std::cout << "k: " << k << ", res: " << res << std::endl;
    }
    t3 += omp_get_wtime();

    std::cout << "t: " << t << std::endl;
    std::cout << "t2: " << t2 << std::endl;
    std::cout << "t3: " << t3 << std::endl;


    return 0;
}

, где runFindShift.cpp:

double runFindShift(double*x, double*y, int arr_length, std::vector<double> xv, std::vector<double>yv)
{
    cv::Mat A(arr_length, 1, CV_64F);
    std::memcpy(A.data, x, arr_length * 1 * sizeof(double));
    cv::Mat B(arr_length, 1, CV_64F);
    std::memcpy(B.data, y, arr_length * 1 * sizeof(double));
    dip::Image inputA(xv.data(), { xv.size() });
    dip::Image inputB(yv.data(), { yv.size() });

    dip::Image im1 = inputA / 255.0;
    dip::Image im2 = inputB / 255.0;
    im1.Squeeze();
    im2.Squeeze();
    double out = dip::FindShift(im1, im2, "MTS")[0];

    return out;
}

Однако серийная версия и pragma omp for работают около 8 секунд, в то время как pragma omp parallel for работает около 15 секунд

Я полагаю, что проблема связана с double out = dip::FindShift(im1, im2, "MTS")[0];, потому что, если я закомментирую это и заменю на double out =0.0, затем серийный номер и pragma omp for работает около 5 сек c, тогда как pragma omp parallel for работает около 4 секунд

Более того, если я заменим res = runFindShift(xarr, yarr, x1.size(), x1, y1); в main следующим :

for (int m = 0; m < 1000000; m++) {
    res = res + m;
}

тогда, последовательный и pragma omp for занимает примерно 146 секунд, а pragma omp parallel for приводит к огромному ускорению, так как это занимает всего 4 секунды

Есть ли способ, которым я могу получить openmp для ускорения даже при использовании dip::FindShift?

EDIT

Новый код ниже:

main.cpp:

int main()
{

    std::vector<double>x1 = {0,0,0,0,0 };
    std::vector<double>y1 = { 0,0,0,0,0 };

    double res=0.0;

    std::string outputDir = "C:/me";

    double t = -omp_get_wtime();
    for (int k = 0; k < 600; k++) {
        for (int j = 0; j < 100; j++) {
            res = runFindShift(x1, y1);
        }
    }
    t += omp_get_wtime();


    res = 0.0;
    double t3 = -omp_get_wtime();
#pragma omp parallel for
    for (int k = 0; k < 600; k++) {
        for (int j = 0; j < 100; j++) {
            res = runFindShift(x1, y1);
        }
    }
    t3 += omp_get_wtime();

    std::cout << "t: " << t << std::endl;
    std::cout << "t3: " << t3 << std::endl;

    return 0;
}

runFindShift.cpp:

double runFindShift(std::vector<double>& xv, std::vector<double>& yv)
{
    dip::Image inputA(xv.data(), { xv.size() });
    dip::Image inputB(yv.data(), { yv.size() });

    dip::Image im1 = inputA / 255.0;
    dip::Image im2 = inputB / 255.0;

    im1.Squeeze();
    im2.Squeeze();

    double out = dip::FindShift(im1, im2, "MTS")[0];
    return out;
}

последовательное время равно 4,3 сек c, а pragma omp parallel for равно 12,3 сек c.

...