Утечка памяти с усилителем 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)" устраняет утечку памяти.