Возникли проблемы с расписанием

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

разница во времени эрозии

мой код без какого-либо планирования:

Halide::Image<uint8_t> erode(Halide::Image<uint8_t> input, int dimension) {
Halide::Var x("x"), y("y");
Halide::Image<uint8_t> output;
Halide::Func limit("limit"), e("e");
limit = Halide::BoundaryConditions::repeat_edge(input);
Halide::RDom r(dimension*-1 / 2, dimension, dimension*-1 / 2, dimension);
e(x, y) = limit(x, y);
e(x, y) = Halide::min(limit(x + r.x, y + r.y), e(x, y));
output = e.realize(input.width(), input.height());
return output;
}

мой код с попыткой тайлинга (я пытался использовать пример, показанный в туториале):

Halide::Image<uint8_t> erodeTiling(Halide::Image<uint8_t> input, int dimension) {
Halide::Var x("x"), y("y"), x_outer, x_inner, y_outer, y_inner, tile_index;
Halide::Image<uint8_t> output;
Halide::Func limit("limit"), e("e");
limit = Halide::BoundaryConditions::repeat_edge(input);
Halide::RDom r(dimension*-1 / 2, dimension, dimension*-1 / 2, dimension);
e(x, y) = limit(x, y);
e(x, y) = Halide::min(limit(x + r.x, y + r.y), e(x, y));
e.tile(x, y, x_outer, y_outer, x_inner, y_inner, 64,64).fuse(x_outer, y_outer, tile_index).parallel(tile_index);
output = e.realize(input.width(), input.height());
return output;
}

Буду очень признателен за любые советы о том, как правильно планировать, так как я все еще новичок в этом.

РЕДАКТИРОВАТЬ: код, используемый для получения времени:

__int64 ctr1 = 0, ctr2 = 0, freq = 0;
output = erode(input, dimension);


if (QueryPerformanceCounter((LARGE_INTEGER *)&ctr1) != 0) {
    // Activity to be timed
    output = erode(input, dimension);
    QueryPerformanceCounter((LARGE_INTEGER *)&ctr2);
    QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
}
std::cout << "\nerosion " << dimension << "x" << dimension << ":" << ((ctr2 - ctr1) *1.0 / freq) << "..."; 
ctr1 = 0, ctr2 = 0, freq = 0;

person Rok    schedule 29.06.2016    source источник


Ответы (1)


Одна большая проблема заключается в том, что вы перекомпилируете конвейер обработки изображений каждый раз, когда хотите стереть изображение. Если вы используете ImageParam для ввода и Param для измерения, вы можете просто скомпилировать его один раз, а затем реализовать его несколько раз на разных изображениях.

Помимо этого, планирование выполняется независимо для каждого этапа Func. Ваш Func состоит из двух этапов (каждая строка, начинающаяся с "e(x, y) =", является этапом), и вы планируете только первый (дешевый) этап. Попробуйте что-то вроде этого, чтобы запланировать инициализацию и обновление одинаково:

e.tile(x, y, x_outer, y_outer, x_inner, y_inner, 64,64).fuse(x_outer, y_outer, tile_index).parallel(tile_index);
e.update(0).tile(x, y, x_outer, y_outer, x_inner, y_inner, 64,64).fuse(x_outer, y_outer, tile_index).parallel(tile_index);

Если размер> 3, вам, вероятно, нужен отделяемый минимальный фильтр. Я бы написал так:

Func minx, miny;
miny(x, y) = minimum(limit(x, y+r));
minx(x, y) = minimum(miny(x+r, y));

minx.parallel(y, 4).vectorize(x, 32);
miny.compute_at(minx, y).vectorize(x, 32);
person Andrew Adams    schedule 29.06.2016
comment
Большое спасибо за ответ. Я попробую, как только смогу. - person Rok; 29.06.2016
comment
на самом деле исправление: ваш пример выдает ошибку: выходной буфер e $ 5 доступен по адресу 119, что превышает максимальное значение (111) в измерении 0 - person Rok; 29.06.2016
comment
также влияет ли изменение в компьютере, который я сейчас использую, на более медленное время? для эрозии я получаю около 0,47071, что намного медленнее, чем мой рабочий компьютер - person Rok; 29.06.2016