Reputation: 1724
I am processing a plenty of 4k images by calculating a parameter on small (64X64 pixel) patches of the image. The task is now being carried out in a sequential fashion, one patch at a time. A snippet of my code is copied below to show you the idea.
for (int i = 0; i < imageW / pSize; i++) {
for (int j = 0; j < imageH / pSize; j++) {
thisPatch = MatrixUtil.getSubMatrixAsMatrix(image, i * pSize, j * pSize, pSize);
results[i][j] = computeParamForPatch(thisPatch);
}
}
I now need to parallelize this to possibly save some time. As you can see, the process for each patch is completely independent from all others. To do so, I either need to remember the location of each patch by using a Map
or use forEachOrdered()
. Unfortunately I don't think using maps, something like Map<Point, double[][]>
would be parallelized. So this is my question: Apart from using forEachOrdered()
which affects the performance negatively, is there any other way to process an image in parallel?
One solution: I tried the following code (suggested by @DHa) which makes a significant improvement:
int outputW = imageW / pSize;
int outputH = imageH / pSize;
IntStream.range(0, outputW * outputH).parallel().forEach(i -> {
int x = (i % outputW);
int y = (i / outputH);
tDirectionalities[x][y] = computeDirectionalityForPatch(
MatrixUtil.computeParamForPatch(image, x * pSize, y * pSize, pSize));
});
Results:
Upvotes: 2
Views: 718
Reputation: 669
This solution uses a parallel stream.
See also How many threads are spawned in parallelStream in Java 8 for how to control amount of threads that work on the stream simultaneously.
int patchWidth = (int)Math.ceil((double)imageW / pSize);
int patchHeight = (int)Math.ceil((double)imageH / pSize);
IntStream.range(0, patchWidth * patchHeight).parallel().forEach(i -> {
int x = (i % patchWidth);
int y = (i / patchWidth);
thisPatch = MatrixUtil.getSubMatrixAsMatrix(image, x * pSize, y * pSize, pSize);
results[x][y] = computeParamForPatch(thisPatch);
});
Upvotes: 2