Я занимаюсь обработкой изображений, для которых я получаю выгоду от векторизации.
У меня есть функция, которая векторизовывает ok, но для которой я не могу убедить компилятор, что входной и выходной буфер не перекрывают друг друга, поэтому проверка псевдонимов не требуется.
Я должен быть в состоянии сделать это с помощью __restrict__
, но если буферы не определены как __restrict__
при приеме в качестве аргумента функции, невозможно убедить компилятор, что я абсолютно уверен, что два буфера никогда не будут перекрываться.
Это функция:
__attribute__((optimize("tree-vectorize","tree-vectorizer-verbose=6")))
void threshold(const cv::Mat& inputRoi, cv::Mat& outputRoi, const unsigned char th) {
const int height = inputRoi.rows;
const int width = inputRoi.cols;
for (int j = 0; j < height; j++) {
const uint8_t* __restrict in = (const uint8_t* __restrict) inputRoi.ptr(j);
uint8_t* __restrict out = (uint8_t* __restrict) outputRoi.ptr(j);
for (int i = 0; i < width; i++) {
out[i] = (in[i] < valueTh) ? 255 : 0;
}
}
}
Единственный способ, с помощью которого я могу убедить компилятор не выполнять проверку псевдонимов, - это включить внутренний цикл в отдельную функцию, в которой указатели определяются как аргументы __restrict__
. Если я объявляю эту внутреннюю функцию вложенной, снова активируется проверка псевдонимов.
Вы также можете увидеть эффект этого примера, который, как мне кажется, согласуется: http://goo.gl/7HK5p7
(Примечание: я знаю, что могут быть лучшие способы написания одной и той же функции, но в этом случае я просто пытаюсь понять, как избежать проверки псевдонимов)
Edit:
Проблема решена!! (См. ответ ниже)
Используя gcc 4.9.2, вот полный пример. Обратите внимание на использование флага компилятора -fopt-info-vec-optimized
вместо замененного -ftree-vectorizer-verbose=N
.
Итак, для gcc используйте #pragma GCC ivdep
и наслаждайтесь!:)