I have the following simple function:
__device__
mirror(int index , int lB, int uB)
{
while(index < lB || index >= uB)
{
if(index < lB) {
index = lB + (lB-index);
}
if(index >= uB) {
index = uB-1 -(index-uB);
}
}
return index;
}
Assume lb <= uB
.
It is used for every index to give it a mirror border behaviour and make sure the result is a valid index.
Are there ways to improve this, with or without changing the result for indices outside [lB-d,uB+d)
, where d >= uB-lB
.
mirror(i,lB,uB)
has to be in [lB,uB)
of course.
What are concerns for performance?
- this function is called very often
- it is called from an kernel (cuda things relevant? thread divergence?)
Are there possible improvments for the special case lB == 0
?
EDIT: added this small test example
__global__
void driver(unsigned char* img_dest, unsigned char* img_src, int width, int height)
{
int x = blockIdx.x*blockDim.x+threadIdx.x;
int y = blockIdx.y*blockDim.y+threadIdx.y;
if(x >= 0 && x < width && y >= 0 && y < height)
{
int x_src = mirror(x*2-width/2,0,width);
assert(x_src >= 0);
assert(x_src < width);
int y_src = mirror(y+x,0,height);
assert(y_src >= 0);
assert(y_src < height);
img_dest[x+y*width] = img_src[x_src + y_src*width];
}
}
// let the images be gray images, with no pitch.
void callDriver(unsigned char* img_dest, unsigned char* img_src, int width,int height)
{
dim3 block(16,16);
dim3 grid((width+block.x-1)/block.x,(height+block.y-1)/block.y);
driver<<<grid,block>>>(img_dest,img_src,width,height);
cudaDeviceSynchronize();
}
main()
{
int width = 512;
int height = 256;
unsigned char* img_dest;
cudaMalloc(&img_dest,width*height);
unsigned char* img_src;
cudaMalloc(&img_src,width*height);
callDriver(img_dest,img_src,width,height);
}
My use case is similar to the driver example: I have functions deforming where I would have to load pixel that would lay outside of the defined region. To provide meaningful values I want to define them by mirroring at the borders.
My use case are distortion, and linear filters. In both cases I have to use values for pixels that are not defined in the image. While in the case of linear filters, there are other possible solutions (starting extra kernel for border), I decided to work with one kernel for this time.
index
be less than zero, too? \$\endgroup\$while
approach, especially considering this is CUDA? \$\endgroup\$index
can have any values betweenINT_MIN
andINT_MAX
, butlB
is0
anduB
is10
, then mirroring is a waste of time. Or iflB
is very high andindex
very low, then we have an overflow that would certainly deprive mirroring of any sense. Do we know anything about those values besideslB <= uB
? \$\endgroup\$