  * TODO List
  *
  * - Resize image to test for speed
- * - Introduce a stride
  * - Think how this can work for images of any size
  * - Think about bank collisions
  * - Refactor the code

    __shared__ unsigned char cache[16][16];

    int stride = 0;
    int tid = (blockIdx.x * gridDim.y * blockDim.x * blockDim.y) + (blockIdx.y * blockDim.x * blockDim.y) + (threadIdx.x * blockDim.y) + threadIdx.y;

    int i = (tid + stride) % width;
    int j = (tid + stride) / width;

    while (i > 0 && i < width - 1 & j > 0 && j < height - 1)
    /*if (i > 0 && i < width - 1 & j > 0 && j < height - 1)*/
    {
        int gradX = tex2D(imageTex, i-1, j+1) - tex2D(imageTex, i-1, j-1) + 2*tex2D(imageTex, i, j+1) - 2*tex2D(imageTex, i, j-1) + tex2D(imageTex, i+1, j+1) - tex2D(imageTex, i+1, j-1);
        int gradY = tex2D(imageTex, i-1, j-1) + 2*tex2D(imageTex, i-1, j) + tex2D(imageTex, i-1, j+1) - tex2D(imageTex, i+1, j-1) - 2*tex2D(imageTex, i+1, j) - tex2D(imageTex, i+1, j+1);

        int magnitude = gradX*gradX + gradY*gradY;

        if (magnitude  > THRESH)
        {
            cache[threadIdx.x][threadIdx.y] = 255;
        }


    // Run the kernel
    int n = 16;
    dim3 dimBlock(source.width/n, 1);
    dim3 dimGrid(n, n);
    filter<<<dimBlock, dimGrid>>>(devGrayScale, devFiltered, filtered.width, filtered.height);

