Советы по отладке трудно воспроизводимых ошибок параллелизма?

#multithreading #debugging #language-agnostic #concurrency

#многопоточность #отладка #не зависит от языка #параллелизм

Вопрос:

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

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

1. Это проблема с повреждением данных (ячейки памяти, переменной или буфера) или проблема с вызовом функции (функции вызываются не по порядку или в неожиданное время)? Методы обнаружения различны.

2. @wong: повреждение данных.

Ответ №1:

Вот мой метод: я обычно использую много assert () для проверки согласованности / достоверности данных как можно чаще. При сбое одного утверждения происходит сбой программы, генерирующей основной файл. Затем я использую отладчик с файлом core, чтобы понять, какая конфигурация потока привела к повреждению данных.

Ответ №2:

Возможно, это не поможет вам, но, вероятно, поможет кому-то, кто столкнется с этим вопросом в будущем.

Если вы используете .Язык Net вы можете использовать проект CHESS от Microsoft Research. Он запускает модульные тесты со всеми видами чередования потоков и показывает вам, какие из них вызывают ошибку.

Возможно, существует аналогичный инструмент для языка, который вы используете.

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

1. Ссылка, похоже, теперь не работает

Ответ №3:

Это сильно зависит от характера проблемы. Обычно полезны разделение пополам (для сужения пространства поиска) код «инструментирование» с утверждениями для доступа к идентификаторам потоков, количеству блокировок / разблокировок, порядку блокировки и т.д. В надежде, что когда проблема повторится в следующий раз, приложение либо зарегистрирует подробное сообщение, либо выполнит дамп ядра, выдающий вам решение.

Ответ №4:

Один из методов обнаружения повреждения данных, вызванного ошибкой параллелизма:

  • Добавьте атомарный счетчик для этих данных или буфера.
    • Оставьте весь существующий код синхронизации как есть — не модифицируйте их, предполагая, что вы собираетесь исправить ошибку в существующем коде, тогда как новый атомарный счетчик будет удален, как только ошибка будет исправлена.
  • Начиная изменять данные, увеличьте атомарный счетчик. По завершении уменьшите.
  • Дамп ядра, как только вы обнаружите, что счетчик больше единицы (используя что-то похожее на InterlockedIncrement)

Ответ №5:

По моему опыту, целевой модульный тестовый код отнимает много времени, но эффективен.

Максимально сократите количество отказывающего кода. Напишите тестовый код, специфичный для очевидного кода-виновника, и запускайте его в отладчике столько времени, сколько потребуется для воспроизведения проблемы.

Ответ №6:

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

Ответ №7:

Если ошибка является взаимоблокировкой, простое подключение средства отладки (например, gdb или strace ) к программе после возникновения взаимоблокировки и наблюдение за тем, где застрял каждый поток, часто может дать вам достаточно информации, чтобы быстро отследить источник ошибки.

Ответ №8:

Я составил небольшую диаграмму с некоторыми приемами отладки, которые следует учитывать при отладке многопоточного кода. График растет, пожалуйста, оставляйте комментарии и подсказки для добавления. http://adec.altervista.org/blog/multithreading-debugging-chart /