Skip to content

Commit 4b1124f

Browse files
committed
Use chunking with LoopBuilder in singleiteration
To multithread the singleiteration function, we need to use the chunked LoopBuilder. This results in about a ~40% reducing in processing time.
1 parent 449d2bc commit 4b1124f

File tree

1 file changed

+66
-63
lines changed

1 file changed

+66
-63
lines changed

scijava-ops-image/src/main/java/org/scijava/ops/image/coloc/saca/AdaptiveSmoothedKendallTau.java

Lines changed: 66 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -124,77 +124,80 @@ private static <I extends RealType<I>> void singleiteration(
124124
{
125125
final double[][] kernel = kernelGenerate(Bsize);
126126

127-
final long[] rowrange = new long[4];
128-
final long[] colrange = new long[4];
129-
final int totnum = (2 * Bsize + 1) * (2 * Bsize + 1);
130-
final double[] LocX = new double[totnum];
131-
final double[] LocY = new double[totnum];
132-
final double[] LocW = new double[totnum];
133-
final double[][] combinedData = new double[totnum][3];
134-
final int[] rankedindex = new int[totnum];
135-
final double[] rankedw = new double[totnum];
136-
final int[] index1 = new int[totnum];
137-
final int[] index2 = new int[totnum];
138-
final double[] w1 = new double[totnum];
139-
final double[] w2 = new double[totnum];
140-
final double[] cumw = new double[totnum];
141-
142127
RandomAccessibleInterval<DoubleType> workingImageStack = Views.stack(oldtau,
143128
newtau, oldsqrtN, newsqrtN, stop.get(0), stop.get(1), stop.get(2));
144129
CompositeIntervalView<DoubleType, ? extends GenericComposite<DoubleType>> workingImage =
145130
Views.collapse(workingImageStack);
146131

147132
IntervalView<Localizable> positions = Views.interval(Localizables
148133
.randomAccessible(result.numDimensions()), result);
149-
final long nr = result.dimension(1);
150-
final long nc = result.dimension(0);
151-
final RandomAccess<I> gdImage1 = image1.randomAccess();
152-
final RandomAccess<I> gdImage2 = image2.randomAccess();
153-
final RandomAccess<DoubleType> gdTau = oldtau.randomAccess();
154-
final RandomAccess<DoubleType> gdSqrtN = oldsqrtN.randomAccess();
155-
LoopBuilder.setImages(positions, result, workingImage).forEachPixel((pos,
156-
resPixel, workingPixel) -> {
157-
DoubleType oldtauPix = workingPixel.get(0);
158-
DoubleType newtauPix = workingPixel.get(1);
159-
DoubleType oldsqrtNPix = workingPixel.get(2);
160-
DoubleType newsqrtNPix = workingPixel.get(3);
161-
DoubleType stop0Pix = workingPixel.get(4);
162-
DoubleType stop1Pix = workingPixel.get(5);
163-
DoubleType stop2Pix = workingPixel.get(6);
164-
final long row = pos.getLongPosition(1);
165-
updateRange(row, Bsize, nr, rowrange);
166-
if (isCheck) {
167-
if (stop0Pix.getRealDouble() != 0) {
168-
return;
169-
}
170-
}
171-
final long col = pos.getLongPosition(0);
172-
updateRange(col, Bsize, nc, colrange);
173-
getData(Dn, kernel, gdImage1, gdImage2, gdTau, gdSqrtN, LocX, LocY, LocW,
174-
rowrange, colrange, totnum);
175-
newsqrtNPix.setReal(Math.sqrt(NTau(thres1, thres2, LocW, LocX, LocY)));
176-
if (newsqrtNPix.getRealDouble() <= 0) {
177-
newtauPix.setZero();
178-
resPixel.setZero();
179-
}
180-
else {
181-
final double tau = WtKendallTau.calculate(LocX, LocY, LocW,
182-
combinedData, rankedindex, rankedw, index1, index2, w1, w2, cumw,
183-
rng);
184-
newtauPix.setReal(tau);
185-
resPixel.setReal(tau * newsqrtNPix.getRealDouble() * 1.5);
186-
}
134+
LoopBuilder.setImages(positions, result, workingImage).multiThreaded()
135+
.forEachChunk(chunk -> {
136+
final long[] rowrange = new long[4];
137+
final long[] colrange = new long[4];
138+
final int totnum = (2 * Bsize + 1) * (2 * Bsize + 1);
139+
final double[] LocX = new double[totnum];
140+
final double[] LocY = new double[totnum];
141+
final double[] LocW = new double[totnum];
142+
final double[][] combinedData = new double[totnum][3];
143+
final int[] rankedindex = new int[totnum];
144+
final double[] rankedw = new double[totnum];
145+
final int[] index1 = new int[totnum];
146+
final int[] index2 = new int[totnum];
147+
final double[] w1 = new double[totnum];
148+
final double[] w2 = new double[totnum];
149+
final double[] cumw = new double[totnum];
150+
final long nr = result.dimension(1);
151+
final long nc = result.dimension(0);
152+
final RandomAccess<I> gdImage1 = image1.randomAccess();
153+
final RandomAccess<I> gdImage2 = image2.randomAccess();
154+
final RandomAccess<DoubleType> gdTau = oldtau.randomAccess();
155+
final RandomAccess<DoubleType> gdSqrtN = oldsqrtN.randomAccess();
156+
chunk.forEachPixel((pos, resPixel, workingPixel) -> {
157+
DoubleType oldtauPix = workingPixel.get(0);
158+
DoubleType newtauPix = workingPixel.get(1);
159+
DoubleType oldsqrtNPix = workingPixel.get(2);
160+
DoubleType newsqrtNPix = workingPixel.get(3);
161+
DoubleType stop0Pix = workingPixel.get(4);
162+
DoubleType stop1Pix = workingPixel.get(5);
163+
DoubleType stop2Pix = workingPixel.get(6);
164+
final long row = pos.getLongPosition(1);
165+
updateRange(row, Bsize, nr, rowrange);
166+
if (isCheck) {
167+
if (stop0Pix.getRealDouble() != 0) {
168+
return;
169+
}
170+
}
171+
final long col = pos.getLongPosition(0);
172+
updateRange(col, Bsize, nc, colrange);
173+
getData(Dn, kernel, gdImage1, gdImage2, gdTau, gdSqrtN, LocX, LocY,
174+
LocW, rowrange, colrange, totnum);
175+
newsqrtNPix.setReal(Math.sqrt(NTau(thres1, thres2, LocW, LocX,
176+
LocY)));
177+
if (newsqrtNPix.getRealDouble() <= 0) {
178+
newtauPix.setZero();
179+
resPixel.setZero();
180+
}
181+
else {
182+
final double tau = WtKendallTau.calculate(LocX, LocY, LocW,
183+
combinedData, rankedindex, rankedw, index1, index2, w1, w2, cumw,
184+
rng);
185+
newtauPix.setReal(tau);
186+
resPixel.setReal(tau * newsqrtNPix.getRealDouble() * 1.5);
187+
}
187188

188-
if (isCheck) {
189-
final double taudiff = Math.abs(stop1Pix.getRealDouble() - newtauPix
190-
.getRealDouble()) * stop2Pix.getRealDouble();
191-
if (taudiff > Lambda) {
192-
stop0Pix.setOne();
193-
newtauPix.set(oldtauPix);
194-
newsqrtNPix.set(oldsqrtNPix);
195-
}
196-
}
197-
});
189+
if (isCheck) {
190+
final double taudiff = Math.abs(stop1Pix.getRealDouble() - newtauPix
191+
.getRealDouble()) * stop2Pix.getRealDouble();
192+
if (taudiff > Lambda) {
193+
stop0Pix.setOne();
194+
newtauPix.set(oldtauPix);
195+
newsqrtNPix.set(oldsqrtNPix);
196+
}
197+
}
198+
});
199+
return null;
200+
});
198201

199202
// TODO: instead of copying pixels here, swap oldTau and newTau every time.
200203
// :-)

0 commit comments

Comments
 (0)