Я использую Boehm-GC в своей программе на C для сборки мусора. Я пытаюсь распараллелить цикл for, который работает с массивом. Массив выделяется через GC_malloc. Когда цикл завершается, массив больше не используется в программе. Я вызываю GC_gcollect_and_unmap, который освобождает массив. Однако, когда я распараллеливаю цикл for с помощью openmp, массив никогда не освобождается после выполнения цикла. Это точно такая же программа, я только добавляю #pragmas вокруг цикла, чтобы распараллелить его. Я попытался посмотреть на код сборки бок о бок с распараллеливанием openmp и без него, я вижу, что указатель массива обрабатывается аналогичным образом, и нигде не вижу дополнительных указателей. Единственное отличие состоит в том, что цикл for реализован как простой цикл внутри основной функции, но когда я его распараллеливаю, openmp создает новую функцию ##name##._omp_fn и вызывает ее. Во всяком случае, мне нужно что-то сделать, чтобы Boehm-GC собирал массив? Мне трудно опубликовать MWE, потому что, если программа достаточно мала, Boehm-GC вообще не сработает.
Вот фрагмент кода без распараллеливания.
struct thing {
float* arr;
int size;
}
int l=10;
static thing* get_randn(void) {
thing* object = (thing*)GC_malloc(sizeof(struct {float* arr, int size}));
object->arr=malloc(sizeof(float)*l);
void finalizer(void *obj, void* client_data)
{
printf("freeing %p\n", obj);
thing* object = (thing*)obj;
free(object->arr);
}
GC_register_finalizer(object, &finalizer, NULL, NULL, NULL);
float *arr = object->arr;
int t_id;
for (t_id = 0; t_id<l; t_id++) {
torch_randn(arr+t_id);
}
return object;
}
Приведенный выше мусор кода собирает объект, созданный функцией. Ниже приведен код с распараллеливанием.
struct thing {
float* arr;
int size;
}
int l=10;
static thing* get_randn(void) {
thing* object = (thing*)GC_malloc(sizeof(struct {float* arr, int size}));
object->arr=malloc(sizeof(float)*l);
void finalizer(void *obj, void* client_data)
{
printf("freeing %p\n", obj);
thing* object = (thing*)obj;
free(object->arr);
}
GC_register_finalizer(object, &finalizer, NULL, NULL, NULL);
float *arr = object->arr;
int t_id;
#pragma omp parallel num_threads(10)
{
#pragma omp for
for (t_id = 0; t_id<l; t_id++) {
torch_randn(arr+t_id);
}
}
return object;
}
Для этого кода объект не подвергается сборке мусора. Трудно воспроизвести проблему только через MWE, потому что сборщик мусора не срабатывает для небольших программ, но я наблюдаю такое поведение, когда запускаю свою полную программу.