Я в основном очень программист на высоком уровне, поэтому думать о вещах, таких как местность процессора, для меня очень нова.Почему мое исполнение плохое? (Noob scheduling)
Я работаю над базовой билинейной демографией (для данных датчика RGGB), и у меня есть алгоритм справа (судя по результатам), но он не работает так же хорошо, как я надеялся (~ 210Mpix/s) ,
Вот мой код (вход является 4640x3472 изображение с одного канала RGGB):
def get_bilinear_debayer(input_raw, print_nest=False):
x, y, c = Var(), Var(), Var()
# Clamp and move to 32 bit for lots of space for averaging.
input = Func()
input[x,y] = cast(
UInt(32),
input_raw[
clamp(x,0,input_raw.width()-1),
clamp(y,0,input_raw.height()-1)]
)
# Interpolate vertically
vertical = Func()
vertical[x,y] = (input[x,y-1] + input[x,y+1])/2
# Interpolate horizontally
horizontal = Func()
horizontal[x,y] = (input[x-1,y] + input[x+1,y])/2
# Interpolate on diagonals
diagonal_average = Func()
diagonal_average[x, y] = (
input[x+1,y-1] +
input[x+1,y+1] +
input[x-1,y-1] +
input[x-1,y+1])/4
# Interpolate on adjacents
adjacent_average = Func()
adjacent_average[x, y] = (horizontal[x,y] + vertical[x,y])/2
red, green, blue = Func(), Func(), Func()
# Calculate the red channel
red[x, y, c] = select(
# Red photosite
c == 0, input[x, y],
# Green photosite
c == 1, select(x%2 == 0, vertical[x,y],
horizontal[x,y]),
# Blue photosite
diagonal_average[x,y]
)
# Calculate the blue channel
blue[x, y, c] = select(
# Blue photosite
c == 2, input[x, y],
# Green photosite
c == 1, select(x%2 == 1, vertical[x,y],
horizontal[x,y]),
# Red photosite
diagonal_average[x,y]
)
# Calculate the green channel
green[x, y, c] = select(
# Green photosite
c == 1, input[x,y],
# Red/Blue photosite
adjacent_average[x,y]
)
# Switch color interpolator based on requested color.
# Specify photosite as third argument, calculated as [x, y, z] = (0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 2)
# Happily works out to a sum of x mod 2 and y mod 2.
debayer = Func()
debayer[x, y, c] = select(c == 0, red[x, y, x%2 + y%2],
c == 1, green[x, y, x%2 + y%2],
blue[x, y, x%2 + y%2])
# Scheduling
x_outer, y_outer, x_inner, y_inner, tile_index = Var(), Var(), Var(), Var(), Var()
bits = input_raw.get().type().bits
output = Func()
# Cast back to the original colour space
output[x,y,c] = cast(UInt(bits), debayer[x,y,c])
# Reorder so that colours are calculated in order (red runs, then green, then blue)
output.reorder_storage(c, x, y)
# Tile in 128x128 squares
output.tile(x, y, x_outer, y_outer, x_inner, y_inner, 128, 128)
# Vectorize based on colour
output.bound(c, 0, 3)
output.vectorize(c)
# Fuse and parallelize
output.fuse(x_outer, y_outer, tile_index)
output.parallel(tile_index)
# Debugging
if print_nest:
output.print_loop_nest()
debayer.print_loop_nest()
red.print_loop_nest()
green.print_loop_nest()
blue.print_loop_nest()
return output
Честно говоря, я никогда не знаю, что я делаю здесь, и я тоже новичок в этом, чтобы иметь любой ключ, где или на что смотреть.
Any Полезно знать, как улучшить планирование. Я все еще участвую, но обратной связи трудно найти.
График, который у меня есть, - это лучшее, что я смог сделать, но это почти полностью проб и ошибок.
EDIT: Я добавил дополнительные 30Mpix/s, выполнив все смежное среднее суммирование в функции напрямую и векторизовать на x_inner вместо цвета.
EDIT: Новый график:
# Set input bounds.
output.bound(x, 0, (input_raw.width()/2)*2)
output.bound(y, 0, (input_raw.height()/2)*2)
output.bound(c, 0, 3)
# Reorder so that colours are calculated in order (red runs, then green, then blue)
output.reorder_storage(c, x, y)
output.reorder(c, x, y)
# Tile in 128x128 squares
output.tile(x, y, x_outer, y_outer, x_inner, y_inner, 128, 128)
output.unroll(x_inner, 2).unroll(y_inner,2)
# Vectorize based on colour
output.unroll(c)
output.vectorize(c)
# Fuse and parallelize
output.fuse(x_outer, y_outer, tile_index)
output.parallel(tile_index)
EDIT: Окончательный график, который сейчас бьется (640MP/с) в Intel Performance Primitive benchmark, который был запущен на процессоре twice as powerful as mine:
output = Func()
# Cast back to the original colour space
output[x,y,c] = cast(UInt(bits), debayer[x,y,c])
# Set input bounds.
output.bound(x, 0, (input_raw.width()/2)*2)
output.bound(y, 0, (input_raw.height()/2)*2)
output.bound(c, 0, 3)
# Tile in 128x128 squares
output.tile(x, y, x_outer, y_outer, x_inner, y_inner, 128, 128)
output.unroll(x_inner, 2).unroll(y_inner, 2)
# Vectorize based on colour
output.vectorize(x_inner, 16)
# Fuse and parallelize
output.fuse(x_outer, y_outer, tile_index)
output.parallel(tile_index)
target = Target()
target.arch = X86
target.os = OSX
target.bits = 64
target.set_feature(AVX)
target.set_feature(AVX2)
target.set_feature(SSE41)
output.compile_jit(target)
Я обновил свой пост с новым расписанием, скорректированным с вашими комментариями. Таким образом, он достигает 360MPix/s, что довольно хорошо. Я знаю, что у Intel есть алгоритм debayer, который получает до 630, хотя: http://www.fastcompression.com/products/debayer/benchmarks.htm – user478250
Векторизация на c ограничена, поскольку есть только три элемента. Иногда вы можете развернуть больший коэффициент, чтобы получить согласованное отображение полосы и обработать сразу несколько векторов информации о цветовых каналах. (Например, Unrolling by 4 дает 3 32x4 вектора одновременно. Вероятно, здесь он работает, так как сырая обработка обычно имеет достаточно большое минимальное ограничение выравнивания - изображения кратно 16 или 32 и т. Д.) Однако лучше было бы vectorize на x, что позволяет увеличить ширину векторизации. В этот момент есть фактор 2, который должен быть выполнен, чтобы вычисление соответствовало 16-битным целым числам. –
Хорошо, поэтому я перепутал вещи в 16-битные целые числа и векторизовал на x_inner, и получил до 480MP/с. Самая большая победа, хотя была вручную указана цель сборки. Когда я вручную попросил 64-битную OSX с AVX, AVX2 и SSE4.1, я получил 640 Мп/с, что превосходит базовый бенчмарк Intel Performance Primitive, несмотря на то, что он работает на процессоре, который наполовину такой же мощный, как тот, на котором тестировался эталон. – user478250