2015-12-30 2 views
1

Я работаю с устройством cuda на интеграционной ветке, и у меня все еще есть некоторый segfault, пока я заканчиваю свою работу.Как избежать утечки памяти на segfault с помощью Cuda

После каждого краха потребление памяти увеличивается на 500 Мо (видно, используя free -m, htop и еще одно, но я не помню названия). Эта память никогда не выпускается на этом компьютере с 4Go оперативной памяти, поэтому мне приходится перезагружаться после некоторых сбоев, в то время как обмен памяти происходит, и это действительно очень медленно (как обычно, когда происходит обмен памяти).

Я знаю, что хороший ответ: «Исправьте свой segfault !!» но я хотел бы понять, почему такое поведение происходит и как я могу его предотвратить.

Я прочитал, что память CUDA должна быть выпущена ОС на segfault, и похоже, что нет.

В то время как я пытался отлаживать свою программу, я замечаю, что если я исправляю segfault, память свободна, но если я также прокомментирую линию выпуска cuda: cudaFreeHost(buf) (с фиксированным segfault), у меня все еще есть утечка памяти ,

. Память выделена как прикрепленные страницы: cudaHostAlloc(&ret, n*sizeof(my_struct), cudaHostAllocPortable).

Я хотел удостовериться, что «бесплатный» код вызывается с использованием unique_ptr, но это не решит проблему с segfault.

Я посмотрел на постоянный режим для CUDA: http://docs.nvidia.com/deploy/driver-persistence/index.html, но он отключен на моем компьютере (я проверил его с nvidia-smi).

Я попытался сбросить устройство cuda: nvidia-smi -r, но он сказал, что он не поддерживается на моем компьютере.

Вопросы являются:

  • Как мы можем задать программу (или ОС), чтобы освободить эти ресурсы в конце программы?
  • Если мы не можем, существует ли команда для восстановления этих ресурсов после сбоя?

Версия:

  • CUDA 6.0.1

  • GCC 4.9.2

  • Driver Версия: 340,65

  • карта: GeForce 610M

Update:

Вот пример кода, чтобы воспроизвести проблему. С прокомментированной строкой я пропущу 10 мо за ход.

#include <cuda.h> 
#include <cuda_runtime.h> 

int main() { 

    int *ret; 
    cudaHostAlloc(&ret, 10000000 * sizeof(*ret), cudaHostAllocPortable); 
    //cudaFreeHost(ret); 
    return 0; 
} 

Update 2:

   total  used  free  shared buffers  cached 
Mem:  3830056 1487156 2342900  66336  142840  527088 
-/+ buffers/cache:  817228 3012828 
Swap:  7811068   0 7811068 
1Erreur de segmentation 
2Erreur de segmentation 
3Erreur de segmentation 
4Erreur de segmentation 
5Erreur de segmentation 
6Erreur de segmentation 
7Erreur de segmentation 
8Erreur de segmentation 
9Erreur de segmentation 
10Erreur de segmentation 
11Erreur de segmentation 
12Erreur de segmentation 
13Erreur de segmentation 
14Erreur de segmentation 
15Erreur de segmentation 
16Erreur de segmentation 
17Erreur de segmentation 
18Erreur de segmentation 
19Erreur de segmentation 
20Erreur de segmentation 
      total  used  free  shared buffers  cached 
Mem:  3830056 1766580 2063476  64152  142860  531032 
-/+ buffers/cache: 1092688 2737368 
Swap:  7811068   0 7811068 
+1

Не могли бы вы разместить короткий пример воспроизведения, который иллюстрирует очевидную утечку памяти? Я не уверен, что ваш диагноз о том, что происходит здесь, является правильным, и может быть, вы неправильно истолковываете то, что происходит. Кроме того, вы используете двухлетний инструментарий CUDA и годовой драйвер. Рассматривали ли вы обновление, чтобы узнать, одинаково ли поведение? – talonmies

+0

Я добавил пример кода для воспроизведения. Я согласен, версия CUDA должна быть актуальной, но у меня не было времени для этой миграции. Я могу/попытаюсь сделать это, чтобы увидеть, произойдет ли это снова. –

+1

Я запустил ваш код 1000 раз в оболочном цикле на 64-битной системе с 16 ГБ оперативной памяти с драйвером 352,39 и временем работы CUDA 6 и вообще не наблюдал утечки памяти. Я не знаю, что происходит с вашим кодом или вашей системой, но CUDA не теряет память хоста при выходе так, как вы предлагаете. – talonmies

ответ

2

Я построил немного измененную версию REPRO случая:

#include <cuda.h> 
#include <cuda_runtime.h> 
#include <signal.h> 

int main() { 

    int *ret; 
    const size_t sz = 1 << 30; 
    cudaHostAlloc(&ret, sz * sizeof(*ret), cudaHostAllocPortable); 
    raise(SIGSEGV); 
    return 0; 
} 

, который на моей системе следует выделить 8Гб возлагали портативной памяти и поднять segfault, что приводит к аномальному выходу и дампу ядра. Я побежал это на машине 16Gb с драйвером 352.39 и CUDA 6 выполнения в цикле оболочки, которая в соответствии с вашим анализом, должен вызвать утечку и кэш обмолота в течение двух или трех прогонов:

$ free; for i in {1..20}; do echo -n $i; ./a.out; done; free 
      total  used  free  shared buffers  cached 
Mem:  16308996 3509924 12799072   0  303588 2313332 
-/+ buffers/cache:  893004 15415992 
Swap:  8257532   0 8257532 
1Segmentation fault (core dumped) 
2Segmentation fault (core dumped) 
3Segmentation fault (core dumped) 
4Segmentation fault (core dumped) 
5Segmentation fault (core dumped) 
6Segmentation fault (core dumped) 
7Segmentation fault (core dumped) 
8Segmentation fault (core dumped) 
9Segmentation fault (core dumped) 
10Segmentation fault (core dumped) 
11Segmentation fault (core dumped) 
12Segmentation fault (core dumped) 
13Segmentation fault (core dumped) 
14Segmentation fault (core dumped) 
15Segmentation fault (core dumped) 
16Segmentation fault (core dumped) 
17Segmentation fault (core dumped) 
18Segmentation fault (core dumped) 
19Segmentation fault (core dumped) 
20Segmentation fault (core dumped) 
      total  used  free  shared buffers  cached 
Mem:  16308996 3510740 12798256   0  303588 2313272 
-/+ buffers/cache:  893880 15415116 
Swap:  8257532   0 8257532 

Однако, вы можете увидеть, что уменьшает только свободную память на 0.006% после выделения 160 ГБ фиксированной памяти и никогда не вызывает API для выпуска памяти или не позволяет коду следовать нормальному коду для выхода. Не произошло утечки памяти или чистого изменения свободных ресурсов.

Драйвер CUDA и среда выполнения освободят ресурсы хоста и GPU на выходе, будь то нормальные или ненормальные, с явными вызовами API без памяти. Я не могу сказать вам, в чем проблема с вашим кодом или системой, но отсутствие освобождения ресурса хоста при выходе приложения из среды выполнения CUDA или драйвера скорее всего не является основной причиной.

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

+0

Я копирую/вставляю код, чтобы выполнить точно такой же тест. Мои результаты: Первый свободный: used = 120550 Второй свободный: used = 1519068 Я использую то же значение, что и вы. Я согласен, что это не полностью утечка, но это 8%, которые нельзя игнорировать.Я знаю, что среда исполнения или драйвера cuda или что-то должно выделять ресурсы, но это явно не полностью сделано в моем случае. –

+0

@ P.Brunet: Можете ли вы опубликовать полный выпуск бесплатных до и после? (возможно, в редактировании вашего вопроса). Это звучит так, будто вы просто неверно истолковываете то, что на самом деле означает выход free/top. 8% -ное изменение полной свободной памяти при распределении половины физической памяти в одном непрерывном буфере не означает, что у вас есть утечка памяти. Ядро Linux динамически резервирует и освобождает кеш-файлы и буферы файловой системы, которые могут легко объяснить несоответствие этого размера. – talonmies

+0

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

Смежные вопросы