Потоки медленные c

#c #multithreading

Вопрос:

я пытаюсь нарисовать Мандельброта и хочу использовать 4 угрозы для выполнения вычисления одновременно , но в другой части изображения, вот функции

 void Mandelbrot(int x_min,int x_max,int y_min,int y_max,Image amp;im)
{

    for (int i = y_min; i < y_max; i  )
    {

        for (int j = x_min; j < x_max; j  )
        {
            //scaled x and y cordinate
            double x0 = mape(j, 0, W, MinX, MaxX);
            double y0 = mape(i, 0, H, MinY, MaxY);

            double x = 0.0f;
            double y = 0.0f;
            int iteration = 0;

            double z = 0;
            while (abs(z)<2.0f amp;amp; iteration < maxIteration)// amp;amp; iteration < maxIteration)
            {

                double xtemp = x * x - y * y   x0;
                y = 2 * x * y   y0;
                x = xtemp;
                iteration  ;

                z = x * x   y * y;

                if (z > 10)//must be 10
                    break;
            }

            int b =mape(iteration, 0, maxIteration, 0, 255);
            if (iteration == maxIteration)
                b = 0;

            im.setPixel(j, i, Color(b,b,0));
        }
    }
}
 

функции mape просто преобразуют число из одного диапазона в другой

Вот функция потока

 void th(Imageamp; im)
{
    float size = (float)im.getSize().x / num_th;
    int x_min = 0, x_max = size, y_min = 0, y_max = im.getSize().y;

    thread t[num_th];
    for (size_t i = 0; i < num_th; i  )
    {

        t[i] = thread(Mandelbrot, x_min, x_max, y_min, y_max, ref(im));
        x_min = x_max;
        x_max  = size;
    }

    for (size_t i = 0; i<num_th; i  )
    {
        t[i].join();
    }

}
 

Основная функция выглядит следующим образом

 int main()
{
   Image img;
   while(1)//here is while window.open()
   {
     th(img);
     //here im drawing

   }
}
 

Так что я не получаю никакого повышения производительности , но это становится еще медленнее , может ли кто-нибудь сказать мне, в чем проблема, что я делаю не так, это тоже случалось со мной раньше

Я задаю вопрос , что такое изображение, это класс из библиотеки SFML, не знаю, поможет ли это.

Комментарии:

1. петля внутри main бесконечна!. завершается ли эта программа?!! Этот код не будет компилироваться или он неполный.

2. @assmo да , это делает условие для цикла, когда окно открыто и рисуется, но проблема не в этом.

3. Сделайте слишком много потоков, и вы замедлите работу системы, поскольку она борется за ядра. Ты это делаешь? Смурфик, если я знаю. У вас есть одновременный несинхронизированный доступ к im . Является ли это проблемой или нет, зависит от встроенных в нее умных setPixel способностей . Так в чем же проблема? Смурфик, если я знаю.

4. В вопросе отсутствует много деталей. Что такое Image ? Как вы выполняете тайминги? Оптимизирована ли сборка? Вы также используете нестандартные функции, такие как массивы переменной длины.

5. @G. M. это из библиотеки sfml

Ответ №1:

Ваш код неполон, чтобы ответить вам конкретно, но есть несколько подозрений:

  1. Создание потока имеет нетривиальные накладные расходы. Если объем работы, выполняемой потоком, недостаточно велик, накладные расходы на его запуск могут стоить больше, чем любые выгоды, которые вы получили бы благодаря параллелизму.
  2. Чрезмерная блокировка и раздоры. Это не похоже на проблему в вашем коде, так как вы, похоже, вообще не используете никаких блокировок. Будьте осторожны (хотя до тех пор, пока они не пишут по одним и тем же адресам, это должно быть правильно).
  3. Ложный общий доступ: Возможная проблема в вашем коде. Строки кэша, как правило, составляют 64 байта. Любая запись в любую часть строки кэша приводит к тому, что вся строка фиксируется в памяти. Если два потока просматривают одну и ту же строку кэша, и один из них записывает в нее, даже если все остальные потоки используют другую часть этой строки кэша, их копия будет признана недействительной и их придется повторно извлекать. Это может вызвать значительные проблемы, если несколько потоков работают с неперекрывающимися данными, которые совместно используют строку кэша, и приводят к этим ошибкам. Если они повторяются с одинаковой скоростью по одним и тем же данным, это может привести к повторению этой проблемы снова и снова. Эта проблема может быть значительной, и ее всегда стоит учитывать.
  4. расположение памяти, приводящее к разгрому вашего кэша. При прохождении через массив переход «поперек» может совпадать с фактическим расположением памяти, считывая одну полную строку кэша за другой, но сканирование «вертикально» касается одной части строки кэша, а затем переходит к соответствующей части другой строки кэша. Если это происходит во многих потоках, и у вас много памяти для обработки, это может означать, что ваш кэш значительно недоиспользуется. Просто нужно остерегаться, независимо от того, является ли ваша машина основной строкой или столбцом, и писать код, соответствующий ей, и избегать скачков в памяти.