Утечка памяти с усилителем C++, но только в режиме освобождения

Я использую усилитель C++ для оценки математических выражений вида (+ x y) в польской нотации. Сложность состоит в том, что выражения задаются в виде деревьев, которые я "компилирую" в линейные инструкции, в основном используя свойство обхода дерева по ширине, которое даст мне список инструкций, которые можно повторять в обратном направлении, чтобы гарантировать, что каждый дочерний элемент узел будет оценен раньше, чем его родитель.

struct amp_instruction
{
  op_code                                            opcode; // add, sub, variable, etc
  int                                                 index; // index of first child
  double                                              value; // for constants
  double                                             weight; // for variables
  std::string                                         label; // node label
  std::shared_ptr<concurrency::array_view<double, 1>>  data; // amp data
};

При создании инструкций я назначаю поле данных следующим образом:

instr.data = make_shared<array_view<double, 1>>(n);

Тогда моя оценка:

array_view<double, 1> amp_interpreter::evaluate(vector<amp_instruction>& instructions)
{
  for (auto &it = rbegin(instructions); it != rend(instructions); ++it)
  {
    switch (it->opcode)
    {
    case ADD:
    {
      array_view<double, 1> a = *instructions[it->index].data;
      array_view<double, 1> b = *instructions[it->index + 1].data;
      parallel_for_each(a.extent, [=](index<1> i) restrict(amp)
      {
        a[i] += b[i];
      });
      it->data = instructions[it->index].data;
      break;
    }
    // other cases... //
    case VARIABLE:
    {
      array_view<double, 1>  a = *it->data;
      array_view<const double, 1> v = *gpu_data[it->label];
      double weight = it->weight;
      parallel_for_each(a.extent, [=](index<1> i) restrict(amp)
      {
        a[i] = v[i] * weight;
      });
      break;
    }
    default: break;
    }
  }
  return *instructions[0].data;
}

где gpu_data - карта, содержащая начальные значения для моих переменных (например, до миллиона). Таким образом, идея заключается в том, чтобы для каждой переменной захватить значения (кэшированные в gpu_data), применить значение веса и сохранить результат в поле данных соответствующей инструкции amp_instruction. Затем данные передаются от дочернего к родительскому для уменьшения выделения памяти в gpu.

Теперь этот код работает нормально, когда я компилирую свою программу в режиме отладки, используя постоянную память около ~1 ГБ для 1000 выражений дерева и 1 М для каждой переменной дерева. Он также выдает правильные значения, поэтому логика работает. Но в режиме релиза использование памяти увеличивается до 10-20 ГБ. Это происходит только с ускорителем по умолчанию, которым является мой Radeon R9 Fury. Основной ускоритель рендеринга не имеет этой проблемы.

У меня железо i7 4790k, 32gb ddr3, Radeon R9 Fury. Может ли это быть проблемой с драйверами? Или, может быть, я не использую усилитель C++, как задумано? Я действительно надеюсь, что кто-то сможет пролить свет на эту проблему, поскольку эта ошибка делает весь подход непригодным для использования.

Благодарю.

1 ответ

Решение

Я не смог точно определить источник утечки памяти, но это определенно происходит из среды выполнения. Изменение параметра "Библиотека времени выполнения" в параметрах проекта с "Многопоточная DLL (/MD)" на "Многопоточная DLL отладки (/MDd)" устраняет утечку памяти.

Другие вопросы по тегам