Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
Холодный Tachyon

Холодный Tachyon

08 Дек 2009

Чуть более месяца назад состоялся первый русскоязычный онлайн-семинар от Intel "Intel Parallel Studio workflow". На нем Кирилл Мавродиев продемонстрировал, как можно распараллелить приложение, рассматривая его как черный ящик. Другими словами, была рассмотрена типичная ситуация, когда у разработчика имеется незнакомый ему код, которые необходимо модернизировать.

Поддержка OpenMP была прекращена в PVS-Studio после версии 5.20. По всем возникшим вопросам вы можете обратиться в нашу поддержку.

Например, распараллелить. В качестве демонстрационного примера была выбрана программа Tachyon, реализующая алгоритм трассировки лучей и рисующая на экране трехмерный фрактал. В качестве инструментария был выбрана технология параллельного программирования OpenMP, компилятор Intel C++, профилировщик многопоточных приложений Parallel Amplifier и инструмент для поиска параллельных ошибок Parallel Inspector. После семинара появилась еще одна запись " По теплым следам онлайн семинара "Intel(R) Parallel Studio workflow""

Мы подумали и решили, раз был пост "по теплым следам", то этот текст уже следует назвать холодным. Есть и еще одна причина. Динамический анализ на этапе исполнения программы, осуществляемый Parallel Inspector, почему-то ассоциируется со словом "горячий". А альтернативный подход, который здесь будет продемонстрирован, основан на статическом анализе исходного кода и скорее ассоциируется со словом "холодный".

Давно было желание привести новый пример использования анализатора VivaMP, входящего в состав PVS-Studio для выявления ошибок в параллельном коде. Оказалось, что этот альтернативный подход к анализу очень хорошо можно продемонстрировать на примере Tachyon. Напомню, что в вебинаре для поиска параллельных ошибок использовался инструмент Parallel Inspector. Диагностика ошибок происходила в несколько этапов. Мы продемонстрируем на этих этапах работу инструмента VivaMP.

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

TachyonStep1\trace.serial.cpp
unsigned int serial = 1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
for (int y = starty; y < stopy; y++) { {
    drawing_area drawing(startx, totaly-y, stopx-startx, 1);
    for (int x = startx; x < stopx; x++) {
       color_t c = render_one_pixel (x, y,
               local_mbox, serial, startx, stopx, starty, stopy);
       drawing.put_pixel(c);
   } }
   if(!video->next_frame()) return;
}

Код совершенно корректен и не вызывает подозрений ни у Parallel Inspector, ни у VivaMP.

Далее код был модифицирован следующим образом:

TachyonStep2\trace.par1.cpp
unsigned int serial = 1;
int ison=1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
#pragma omp parallel for
for(int y = starty; y < stopy*ison; y++) { {
    drawing_area drawing(startx, totaly-y, stopx-startx, 1);
    for (int x = startx; x < stopx; x++) {
      color_t c = render_one_pixel (x, y,
                local_mbox, serial, startx, stopx, starty, stopy);
        drawing.put_pixel(c);
    } }
    if(!video->next_frame()) ison=0;
 }

Такое смелое распараллеливание привело к ошибке и построению некорректного изображения на экране. С помощью Parallel Inspector, было выяснено, что в коде возникает несколько ошибок состояния гонки (race condition). Результатом изучения диагностических сообщений Parallel Inspector было решение объявить переменные ison, local_mbox и serial приватными (shared), то есть уникальными для каждого потока. Именно при обращении к этим переменным возникали гонки. Теперь посмотрим, какие предупреждения для этого кода выдает анализатор VivaMP:

1 error V1206: Data race risk. The value of the 'scene' variable can be changed concurrently via the 'camray' function. r:\src\tachyonstep2\trace.par1.cpp 87

2 error V1206: Data race risk. The value of the 'local_mbox' variable can be changed concurrently via the 'render_one_pixel' function. r:\src\tachyonstep2\trace.par1.cpp 157

3 error V1206: Data race risk. The value of the 'serial' variable can be changed concurrently via the 'render_one_pixel' function. r:\src\tachyonstep2\trace.par1.cpp 157

4 error V1205: Data race risk. Unprotected concurrent operation with the 'ison' variable. r:\src\tachyonstep2\trace.par1.cpp 160

Обратите внимания, что анализатор VivaMP предупредил о потенциальных ошибках гонки для тех же трех переменных: ison, local_mbox и serial. Есть еще одна потенциальная ошибка использования переменной 'camray' в другой функции, но этот момент мы рассмотрим позже.

Основываясь на диагностике Parallel Inspector, код был изменен следующим образом:

TachyonStep2\trace.par2.cpp
unsigned int serial = 1;
int ison=1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
#pragma omp parallel for firstprivate(ison,local_mbox,serial)
for(int y = starty; y < stopy*ison; y++) { {
  drawing_area drawing(startx, totaly-y, stopx-startx, 1);
  for (int x = startx; x < stopx; x++) {
    color_t c = render_one_pixel (x, y,
            local_mbox, serial, startx, stopx, starty, stopy);
    drawing.put_pixel(c);
  } }
  if(!video->next_frame()) ison=0
}

Измененная программа по-прежнему продолжает вести себя некорректно, хотя это и выражается иным образом. Повторный анализ с помощью Parallel Inspector выявляет ошибку совместного использования одного массива local_mbox. Директива firstprivate(local_mbox) создает уникальный указатель для каждого из потока. Но сам массив, на который ссылаются эти указатели, по-прежнему общий.

Анализатор VivaMP также смог диагностировать эту проблему (см. второе предупреждение):

1 error V1206: Data race risk. The value of the 'scene' variable can be changed concurrently via the 'camray' function. r:\src\tachyonstep3.1\trace.par2.cpp 87

2 error V1209: Warning: The 'local_mbox' variable of pointer type should not be private. r:\src\tachyonstep3.1\trace.par2.cpp 153

Ниже приведен окончательный вариант функции, в которой устранены все дефекты, и программа корректно строит изображение фрактала:

TachyonStep2\trace.par3.cpp
#pragma omp parallel
{
unsigned int serial = 1;
int ison=1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
#pragma omp for
for(int y = starty; y < stopy*ison; y++) { {
  drawing_area drawing(startx, totaly-y, stopx-startx, 1);
  for (int x = startx; x < stopx; x++) {
    color_t c = render_one_pixel (x, y,
            local_mbox, serial, startx, stopx, starty, stopy);
    drawing.put_pixel(c);
  } }
  if(!video->next_frame()) ison=0
 }
}

Это код уже не вызывает у Parallel Inspector подозрений. А вот VivaMP по-прежнему выдает одно диагностическое сообщение, являющееся ложным:

1 error V1206: Data race risk. The value of the 'scene' variable can be changed concurrently via the 'camray' function. r:\src\tachyonstep3.2\trace.par3.cpp 87

Это сообщение относится к вызываемой параллельно функции render_one_pixel. В ней VivaMP не может разобраться, что объект scene используется в нескольких потоках только для чтения. Можно легко убрать это сообщение, если объявить функцию чуть более изящно. Достаточно сделать параметр функции scenedef константным. То есть заменить

ray  camray(scenedef *, int, int);

на

ray  camray(const scenedef *, int, int);

После этой модификации анализатор VivaMP не выдаст более ни одного предупреждения.

Итак, задача поиска дефектов в параллельном коде Tachyon решена альтернативным методом. Показанный способ, не лучше и не хуже. Статический анализ быстр, позволяет искать многие ошибки еще на этапе кодирования. Динамический анализ диагностирует большее количество ошибок и с большей достоверностью. Эти два метода могут успешно дополнять друг друга на различных этапах разработки программного обеспечения.

Популярные статьи по теме
Обрабатывать ли в PVS-Studio вывод других инструментов?

Дата: 26 Май 2022

Автор: Андрей Карпов

Анализатор PVS-Studio умеет "схлопывать" повторяющиеся предупреждения. Предоставляет возможность задать baseline, что позволяет легко внедрять статический анализ в legacy-проекты. Стоит ли предостави…
15000 ошибок в открытых проектах

Дата: 24 Май 2022

Автор: Андрей Карпов

Количество багов в нашей коллекции перевалило за отметку 15000. Именно такое количество ошибок обнаружила команда PVS-Studio в различных открытых проектах. Особенно интересно, что это всего лишь побо…
Комментарии в коде как вид искусства

Дата: 04 Май 2022

Автор: Сергей Хренов

Приветствую всех программистов, а также сочувствующих. Кто из нас хотя бы раз в жизни не оставлял комментарии в коде? Был ли это ваш код, а может, чужой? Что за комментарии вы написали: полезные или …
Visual Studio 2022 стильно и свежо. История о её поддержке в PVS-Studio

Дата: 15 Фев 2022

Автор: Николай Миронов

Кажется, анонс Visual Studio 2022 был только недавно, и вот она уже вышла. Это означало ровно одно – поддержать данную IDE нужно в ближайшем релизе PVS-Studio. О том, с какими сложностями пришлось ст…
Лучшие срабатывания статического анализатора

Дата: 29 Окт 2021

Автор: Максим Звягинцев

У всех, кто запускал статический анализатор в первый раз на большом проекте, был небольшой шок по поводу сотен, тысяч или даже десятков тысяч предупреждений. Как-то грустно становится после такого. Т…

Комментарии (0)

Следующие комментарии
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять