Доброго здравия!
Unified Parallel C (UPC) — это расширение языка C, разработанное для высокопроизводительных вычислений на крупномасштабных параллельных машинах. Язык представляет единую программную модель для систем с общей и разделенной памятью. Количество параллелизма фиксируется на старте программы, обычно с одним потоком на ядро процессора.
» Официальный сайт UPC
» Официальный сайт Berkeley UPC
В прошлой статье Установка в среде Windows и Linux описано, как выполнить установку UPC, но остался не раскрытым важный вопрос использования отладки. Очень часто наступает крах программы, если где-то неправильно выделена память или происходит превышение размерности массива
*** Caught a fatal signal: SIGSEGV(11) on node 0/1
NOTICE: Before reporting bugs, run with GASNET_BACKTRACE=1 in the environment to generate a backtrace.
Ошибка сегментирования (слепок снят)
Что можно сделать в данной ситуации, чтобы бы сузить место поиска? Об этом в текущей статье.
Долгое время я избегал изучение отладки, т.к. уже нужно было заняться программированием. Вместо отладки я достаточно подробно логировал через printf действия каждого потока. Однако, дело омрачается тем, что программа UPC переводится на С и в общем случае оказывается не интерпретируемой. Если какая-то строчка была успешно выполнена (по логам), а следующего лога не произошло, то не факт, что ошибка между логируемыми строками! Очень часто ошибка «будущего» влияет на текущую ситуацию и вызывает крах программы совсем в другом месте.
Если в порядке с английским, полную информацию по отладке можно найти на официальной странице Debugging Berkeley UPC applications.
Если у вас есть почтовый ящик в домене университета, то вы можете запросить студенческую лицензию рекомендуемого TotalView, если нет, то можно воспользоваться штатным отладчиком С.
Нужно обратить внимание, что после перевода на С функция main() превратится в user_main().
Первое, чтобы воспользоваться специальным режимом отладки, необходимо запускать upcc c параметром -g
. Это означает, что будет запускаться специальная конфигурация UPC из подпапки dbg. Чтобы была возможность увидеть конкретные строки кода, необходимо сохранить во время компиляции временные файлы с исходниками с помощью параметра -save-temps
:
upcc ./Pack_Polycubes.upc -o Pack_Polycubes -pthreads -save-temps -g
Существует несколько точек входа в отладку. Можно остановить поток с определенным номером с помощью параметра -freeze[=<thread_id>]
, а можно просто остановиться по ошибке с помощью -freeze-on-error
:
upcrun -n 1 -freeze-on-error ./Pack_Polycubes
— WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
This application was built from a Berkeley UPC installation that
was configured and built with these optional features enabled:
debugging tracing statistical collection debugging malloc
This usually has a SERIOUS impact on performance, so you should NOT
trust any performance numbers reported in this program run!!!To suppress this message, pass ‘-quiet’ to the upcrun command or set
the UPC_NO_WARN or UPC_QUIET environment variables.
— UPCR: UPC thread 0 of 1 on Rosa-VB (pshm node 0 of 1, process 0 of 1, pid=31257)
Hello, I am 0 of 1.
…
*** Caught a fatal signal: SIGSEGV(11) on node 0/1
Process frozen for debugger: host=Rosa-VB pid=31257
To unfreeze, attach a debugger and set ‘gasnet_frozen’ to 0, or send a SIGCONT
Далее необходимо запустить gdb еще в одном сеансе консоли из папки с выходными файлами компиляции и указать PID потока
gdb Pack_Polycubes.o 31257
GNU gdb (Linaro GDB) 7.7.1_2014.06_1-10 ()
Copyright © 2014 Free Software Foundation, Inc.
…
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007f0afab16cd0 in __nanosleep_nocancel () from /lib64/libc.so.6
Чтобы продолжить выполнение программы, необходимо выполнить следующий код:
(gdb) set gasnet_frozen = 0
(gdb) continue
Программа услужливо сообщает строчку с ошибкой:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004289f8 in MultiplyMatrixPackSpace (Result=0x26274ac, Matrix=0x2696340, CurPackSpace=0x7ffd81634020)
at ./Pack_Polycubes.upc:1065
1065 Result[row][col] = 0;
Чтобы посмотреть подробнее текущую точку останова, можно воспользоваться командой
(gdb) list
1060 // Умножение по правилу «строка на столбец»
1061 for(row = 0; row < Params.Demension; row++)
1062 {
1063 for(col = 0; col < Params.Demension; col++)
1064 {
1065 Result[row][col] = 0;
Кто бы мог подумать. Пойду разбираться с индексами и выделенной памятью ))
Чтобы узнать стек вызова, можно воспользоваться командой bt
(gdb) bt
#0 0x00000000004289f8 in MultiplyMatrixPackSpace (Result=0x26274ac, Matrix=0x2696340, CurPackSpace=0x7ffd81634020)
#1 0x0000000000428680 in CheckIndependancePS (CurPackSpace=0x7ffd81634020) at ./Pack_Polycubes.upc:1032
#2 0x0000000000428430 in AddIndependentPackSpace (CurPackSpace=0x7ffd81634020) at ./Pack_Polycubes.upc:1011
…
#8 0x0000000000427e21 in ExplorePackSpaces () at ./Pack_Polycubes.upc:922
#9 0x00000000004244c5 in user_main (argc=4, argv=0x7ffd816344e8) at ./Pack_Polycubes.upc:214…
Стек вызова нужно рассматривать с низу. Пользовательская программа начинается с user_main, далее последовательно идут вызовы и видно, в каком месте и с какими параметрами происходит ошибка.
Чтобы корректно выйти из отладки, необходимо продолжить дальше, после чего можно сделать quit
.
(gdb) continue
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
Если по какой-то причине отладочные процессы зависли их можно убить с помощью команды kill
из другого окна консоли, но в Росе получается проще с помощью Ctrl^C.
Наиболее востребованные команды gdb:
break [file:]functiop
— установить точку остановки на функции
bt
— вызвать стек
print expr
— вывести значение выражения
с
— продолжить выполнение программы
next
— выполнить следующую строчку программы (перепрыгнуть)
step
— шагнуть внутрь строчки программы
list
— просмотр текущей строчки останова
help
— вызвать помощь
quit
— выход
И как обычно, man gdb
Благодарю за внимание! Надеюсь, кому-нибудь пригодится
ссылка на оригинал статьи https://habrahabr.ru/post/317196/
Добавить комментарий