Я использую усилитель C++ для вычисления математических выражений формы (+ x y) в лаконичной нотации. Теперь сложная часть заключается в том, что выражения даются как деревья, которые я «компилирую» в линейные инструкции, в основном используя свойство, что пересечение ширины дерева даст мне список инструкций, которые можно повторить назад, чтобы каждый ребенок узел будет оценен перед его родителем.Утечка памяти с помощью усилителя C++, но только в режиме деблокирования
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.
Теперь этот код отлично работает при компиляции моей программы в режиме отладки с использованием постоянной памяти около ~ 1gb для 1000 выражений дерева и значений 1M для каждой переменной дерева. Он также дает правильные значения, поэтому логика работает. Но в режиме деблокирования использование памяти достигает 10-20 гб. Это происходит только с ускорителем по умолчанию, который является моим radeon r9 fury. У этого основного ускорителя нет такой проблемы.
Мое оборудование i7 4790k, 32gb ddr3, radeon r9 fury. Это может быть проблема с драйвером? Или, может быть, я не использую усилитель C++, как предполагалось? Я действительно надеюсь, что кто-то может пролить свет на этот вопрос, поскольку эта ошибка делает весь подход непригодным.
Спасибо.
Это может быть проще отладить с меньшим тестовым случаем :-) – AndyG
Вы могли бы инициализировать до нуля все числовые члены 'ai'? в общем, возможно, вы могли бы создать конструктор по умолчанию для вашего класса 'amp_instruction', который обнуляет все целые и двойные поля? Отладка/устранение различий в поведении часто происходит от унифицированных переменных в release/0 при отладке. –
Я пробовал, но ничего не меняет. Код также был проверен против стандартной (только для процессора) реализации одной и той же вещи, и он всегда производит правильные значения. Единственная проблема заключается в том, что он утечки памяти в режиме деблокирования. –