for循环优化Java并行计算多线程,有没有解决方案?

for (int i = 0; i < data.length; i++) {

data[i] = Math.sqrt(Math.pow(uData[i], 2) + Math.pow(vData[i], 2));

}

是需要计算风速
一次length 大概有6500个,但是要计算 1500个层次。 相当于要计算 1500 * 6500
目前是用for循环,大概全部完成需要250~300秒。

也试过手动创建多线程跑,计算时间并没有改善,不知道为什么。

private double[] parallelHandelWindData(double[] dataU, double[] dataV) throws InterruptedException {

Integer length = dataU.length;

double[] data = new double[length];

//创建一个线程池

ExecutorService executorService = new ThreadPoolExecutor(

10,

10,

20,

TimeUnit.SECONDS,

new LinkedBlockingDeque<>(5),

Executors.defaultThreadFactory(),

new ThreadPoolExecutor.DiscardOldestPolicy());

List<Runnable> tasks = new ArrayList<>();

for (Integer i = 0; i < 8; i++) {

int startIndex = length / 8 * i;

int endIndex = length / 8 * (i + 1);

double[] uDataBlock = ArrayUtil.sub(dataU, startIndex, endIndex);

double[] vDataBlock = ArrayUtil.sub(dataV, startIndex, endIndex);

tasks.addAll(Arrays.asList(() -> sqrtAndPowWindData(data, uDataBlock, vDataBlock, startIndex, endIndex)));

}

//逐个提交任务

tasks.forEach(executorService::submit);

executorService.shutdown();

// 线程池最大有效执行时间

executorService.awaitTermination(10, TimeUnit.MINUTES);

return data;

}

private double[] sqrtAndPowWindData(double[] data, double[] uDataBlock, double[] vDataBlock, int startIndex, int endIndex) {

for (int i = startIndex; i < endIndex; i++) {

data[i] = Math.sqrt(Math.pow(uDataBlock[i-startIndex], 2) + Math.pow(vDataBlock[i-startIndex], 2));

}

return data;

}


回答:

先确定问题在哪,再提问,你的代码中的 Math 这点计算量,完全不够当代计算机看的。

这是我模拟的代码,运行 1500 次,每次生成两组 6500 长度的 double 数组,两个数组执行你的方法,平均 350 毫秒执行完成,我的机器是 mac m1 pro,即使是再差的机器,也不会比这个数值高到哪里去。

    private static void sqrtAndPowWindData(Double[] uData, Double[] vData) {

for (int i = 0; i < uData.length; i++) {

Math.sqrt(Math.pow(uData[i], 2) + Math.pow(vData[i], 2));

}

}

public static void main(String[] args) {

long start = System.currentTimeMillis();

for (int j = 0; j < 1500; j++) {

List<Double> d1List = new ArrayList<>();

List<Double> d2List = new ArrayList<>();

for (int i = 0; i < 6500; i++) {

d1List.add(RandomUtil.randomDouble());

d2List.add(RandomUtil.randomDouble());

}

sqrtAndPowWindData(ArrayUtil.toArray(d1List, Double.class), ArrayUtil.toArray(d2List, Double.class));

}

System.out.println(System.currentTimeMillis() - start);

因此,只可能消耗大量时间的地方是你获取数据的部分。


回答:

看看数据结果能缓存不? 计算平方的. 计算过的值, 不要再次计算了, 直接保存起来, 用空间换时间.


回答:

同意@zxdposter 的回答,你先看看耗时究竟在哪
但从代码看的话,只是普通数学计算,量级也不大,不应该这么久

量级大的话可以考虑:Flink之类的框架来做


回答:

这个类应该可以用,代码包含了使用示例:

import java.util.Arrays;

import java.util.concurrent.*;

import java.util.function.BiFunction;

import java.util.function.Consumer;

public class ParallelArrayComputing {

private final ExecutorService threadPool;

public ParallelArrayComputing(int threadPoolSize) {

threadPool = new ThreadPoolExecutor(

threadPoolSize, threadPoolSize, 20, TimeUnit.SECONDS,

new LinkedBlockingDeque<>(5), Executors.defaultThreadFactory(),

new ThreadPoolExecutor.DiscardOldestPolicy()

);

}

public void shutdownNow() {

this.threadPool.shutdownNow();

}

public void shutdownAndWait() throws InterruptedException {

this.threadPool.shutdown();

this.threadPool.awaitTermination(1, TimeUnit.HOURS);

}

/**

* 投喂数据

*

* @param u 数据1

* @param v 数据2

* @param calculation 计算方法

* @param whenComplete 当完成计算时要做的事

*/

public void feed(

double[] u, double[] v,

BiFunction<double[], double[], double[]> calculation,

Consumer<double[]> whenComplete

) {

if (u == null || v == null || u.length != v.length) {

throw new IllegalArgumentException();

}

if (u.length == 0) {

whenComplete.accept(new double[0]);

return;

}

threadPool.execute(() -> {

double[] result = calculation.apply(u, v);

whenComplete.accept(result);

});

}

//////////////////////////// 使用方法

public static void main(String[] args) throws InterruptedException {

// 定义计算方法

BiFunction<double[], double[], double[]> calculation = (u, v) -> {

double[] result = new double[u.length];

for (int i = 0; i < result.length; i++) {

result[i] = Math.sqrt(Math.pow(u[i], 2) + Math.pow(v[i], 2));

}

return result;

};

// 定义对结算结果的处理

Consumer<double[]> outputResult =

result -> System.out.println("Finished: " + Arrays.toString(result));

// 初始化 ParallelArrayComputing 对象

ParallelArrayComputing pac = new ParallelArrayComputing(3);

// 投喂一组数据

double[] u = new double[]{1, 2, 3};

double[] v = new double[]{4, 5, 6};

pac.feed(u, v, calculation, outputResult);

// 等待所有计算完成后关闭

pac.shutdownAndWait();

}

}

以上是 for循环优化Java并行计算多线程,有没有解决方案? 的全部内容, 来源链接: utcz.com/p/944652.html

回到顶部