используя несколько потоков одновременно C ++ - PullRequest
0 голосов
/ 01 мая 2018

У меня проблемы с использованием нескольких потоков для моей программы madelbrot.

Один из способов, которым я устала после урока

    int sliceSize = 800 / threads;
    double start = 0, end = 0;
    for (int i = 0; i < threads; i++)
    {
        start = i * sliceSize;
        end = ((1 + i) * sliceSize);

        thrd.push_back(thread(compute_mandelbrot, left, right, top, bottom, start, end));

    }

    for (int i = 0; i < threads; i++)
    {
        thrd[i].join();
    }
    thrd.clear();

но для вычисления кода требуется только половина времени при использовании 8 потоков.

Я также попробовал что-то более сложное, но оно совсем не работает

void slicer(double left, double right, double top, double bottom)
{
    /*promise<int> prom;
    future<int> fut = prom.get_future();*/


    int test = -1;
    double start = 0, end = 0;
    const size_t nthreads = std::thread::hardware_concurrency(); //detect how many threads cpu has
    {
        int sliceSize = 800 / nthreads;

        std::cout << "CPU has " << nthreads << " threads" << std::endl;
        std::vector<std::thread> threads(nthreads);

        for (int t = 0; t < nthreads; t++)
        {

            threads[t] = std::thread(std::bind(
                [&]()
            {

                mutex2.lock();
                test++;

                start = (test) * sliceSize;
                end = ((test + 1) * sliceSize);

                mutex2.unlock();

                compute_mandelbrot(left, right, top, bottom, start, end);


            }));
        }
        std::for_each(threads.begin(), threads.end(), [](std::thread& x) {x.join(); }); //join threads
    }
}

но, похоже, он вычисляет 8 вещей одновременно, они склонны к коленям даже после использования мьютекса, и это не так быстро.

Это дало мне головную боль за последние 7 часов, и я хочу покончить с собой. Помогите.

1 Ответ

0 голосов
/ 01 мая 2018

Когда вы пытаетесь ускорить рабочую нагрузку с помощью многопоточности, многое можно сделать, и в идеальном мире получить ускорение Nx при умножении на N потоков практически невозможно. Некоторые вещи, которые нужно иметь в виду:

  1. Если вы используете гиперпоточность (например, используя 1 поток на виртуальное ядро ​​в системе, а не только на физическое ядро), то вы не получите эквивалентную производительность 2 реальных ядер - вы получите некоторый процент (вероятно, около 1.2x или около того).
  2. Операционная система (Windows) будет работать во время выполнения ваших рабочих нагрузок. Это довольно случайно, что и когда эти задачи ОС сокращают время вашего приложения, но это будет иметь значение. Всегда ожидайте, что какой-то процент вашего процессорного времени будет украден окнами.
  3. Любая синхронизация сильно повлияет на производительность. Во втором примере мьютексы довольно здоровенные и, вероятно, повлияют на производительность.
  4. Доступ к памяти, кэш-памяти и т. Д., Чтобы войти в игру. Несколько потоков, обращающихся к памяти повсеместно, приведут к давлению на кеш, что окажет (потенциальное) влияние.

Мне любопытно - на какие времена вы здесь смотрите? И сколько итераций вы проходите в каждом потоке? Чтобы покопаться и посмотреть, что происходит по времени, вы можете попробовать что-то вроде записи времени начала / окончания каждого потока, используя queryPerformanceCounter, чтобы увидеть, как долго каждый из них работает, когда он запускается и т. Д. 4 и 8 нитей могут пролить немного света.

Надеюсь, это хоть немного поможет ...

...