The following is my attempt at parallelization (I learned about parallel computing last weekend, so I'm very new to it) and making the code more efficient in my previous question Block Bootstrap Estimation using Java. The text.txt text file can be found at https://drive.google.com/open?id=1vLBoNmFyh4alDZt1eoJpavuEwWlPZSKX (download the file directly if you want to try it out – there are some weird things you won't select) above even via Notepad notes). This is a small 10×10 data set with `maxBlockSize = 10`

, but this needs to scale up to twenty 5000 x 3000 data sets with `maxBlockSize = 3000`

, just to get an idea of the scale.

```
import java.io.FileInputStream;
import java.lang.Math;
import java.util.Scanner;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.DoubleStream;
public class BlockBootstrapTestParallel {
// Sum of a subarray, based on B(x, i, L) -- i is one-indexing
public static double sum(double() x, int i, int L) {
return IntStream.range(i, i + L)
.parallel()
.mapToDouble(idx -> x(idx - 1))
.sum();
}
// Mean of a subarray, based on B(x, i, L) -- i is one-indexing
public static double mean(double() x, int i, int L) {
return IntStream.range(i, i + L)
.parallel()
.mapToDouble(idx -> x(idx - 1))
.average()
.orElse(0);
}
// Compute MBB mean
public static double mbbMu(double() x, int L) {
return IntStream.range(0, x.length - L + 1)
.parallel()
.mapToDouble(idx -> mean(x, idx + 1, L))
.average()
.orElse(0);
}
// Compute MBB variance
public static double mbbVariance(double() x, int L, double alpha) {
return IntStream.range(0, x.length - L + 1)
.parallel()
.mapToDouble(idx -> (Math.pow(L, alpha) * Math.pow(mean(x, idx + 1, L) - mbbMu(x, L), 2)))
.average()
.orElse(0);
}
// Compute NBB mean
public static double nbbMu(double() x, int L) {
return IntStream.range(0, x.length / L)
.parallel()
.mapToDouble(idx -> (mean(x, 1 + ((idx + 1) - 1) * L, L)))
.average()
.orElse(0);
}
// Compute NBB variance
public static double nbbVariance(double() x, int L, double alpha) {
double varSum = IntStream.range(0, x.length / L)
.parallel()
.mapToDouble(idx -> (Math.pow(mean(x, 1 + ((idx + 1) - 1) * L, L) - nbbMu(x, L), 2)))
.average()
.orElse(0);
return Math.pow((double) L, alpha) * varSum;
}
// factorial implementation
public static double factorial(int x) {
double() fact = {1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, 3628800.0};
return fact(x);
}
// Hermite polynomial
public static double H(double x, int p) {
double out = 0;
for (int i = 0; i < (p / 2) + 1; i++) {
out += Math.pow(-1, i) * Math.pow(x, p - (2 * i)) /
((factorial(i) * factorial(p - (2 * i))) * (1L << i));
}
out *= factorial(p);
return out;
}
// Row means
public static double() rowMeans(double()() x, int nrows, int ncols) {
double() means = new double(nrows);
for (int i = 0; i < nrows; i++) {
means(i) = mean(x(i), 1, ncols);
}
return means;
}
public static void duration(long start, long end) {
System.out.println("Total execution time: " + (((double)(end - start))/60000) + " minutes");
}
public static void main(String() argv) throws IOException {
final long start = System.currentTimeMillis();
FileInputStream fileIn = new FileInputStream("test.txt");
FileOutputStream fileOutMBB = new FileOutputStream("MBB_test.txt");
FileOutputStream fileOutNBB = new FileOutputStream("NBB_test.txt");
FileOutputStream fileOutMean = new FileOutputStream("means_test.txt");
Scanner scnr = new Scanner(fileIn);
PrintWriter outFSMBB = new PrintWriter(fileOutMBB);
PrintWriter outFSNBB = new PrintWriter(fileOutNBB);
PrintWriter outFSmean = new PrintWriter(fileOutMean);
// These variables are taken from the command line, but are inputted here for ease of use.
int rows = 10;
int cols = 10;
int maxBlockSize = 10; // this could potentially be any value <= cols
int p = 1;
double alpha = 0.1;
double()() timeSeries = new double(rows)(cols);
// read in the file, and perform the H_p(x) transformation
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
timeSeries(i)(j) = H(scnr.nextDouble(), p);
}
scnr.next(); // skip null terminator
}
// row means
double() sampleMeans = rowMeans(timeSeries, rows, cols);
for (int i = 0; i < rows; i++) {
outFSmean.print(sampleMeans(i) + " ");
}
outFSmean.println();
outFSmean.close();
new Thread(() -> {
for (int j = 0; j < rows; j++) {
for (int m = 0; m < maxBlockSize; m++) {
outFSMBB.print(mbbVariance(timeSeries(j), m + 1, alpha) + " ");
}
outFSMBB.println();
}
outFSMBB.close();
}).start();
new Thread(() -> {
for (int j = 0; j < rows; j++) {
for (int m = 0; m < maxBlockSize; m++) {
outFSNBB.print(nbbVariance(timeSeries(j), m + 1, alpha) + " ");
}
outFSNBB.println();
}
outFSNBB.close();
}).start();
duration(start, System.currentTimeMillis());
}
}
```

If it's useful, I have 8 cores available with 64GB of RAM, as well as two GPUs that I have no idea how to use (Intel UHD Graphics 630, NVIDIA Quadro P620). I will see how to use them in the coming days if necessary.