Spo*_*ice 1 java multithreading loops multiprocessing threadpool
这可能是一个非常简单的问题,但是在我认为之前我从未使用过线程,最好不要试图完全依靠自己找到最佳解决方案.
我有一个巨大的for循环,几十亿次运行.在每个循环运行中,根据当前index,程序以数字的形式计算最终结果.我只对存储顶部result(或顶部x结果)及其相应的索引感兴趣.
我的问题很简单,在线程中运行此循环的正确方法是什么,因此它使用所有可用的CPU /核心.
int topResultIndex;
double topResult = 0;
for (i=1; i < 1000000000; ++i) {
double result = // some complicated calculation based on the current index
if (result > topResult) {
topResult = result;
topResultIndex = i;
}
}
Run Code Online (Sandbox Code Playgroud)
对于每个索引,计算完全独立,不共享资源.topResultIndex并且topResult显然会被每个线程访问.
*更新:Giulio和rolfl的解决方案都很好,也非常相似.只能接受其中一个作为我的答案.
假设结果是由一个calculateResult(long)私有和静态的方法计算的,并且不访问任何静态字段(它也可以是非静态的,但它仍然必须是线程安全的并且可以同时执行,希望线程 -限制).
然后,我认为这将做肮脏的工作:
public static class Response {
int index;
double result;
}
private static class MyTask implements Callable<Response> {
private long from;
private long to;
public MyTask(long fromIndexInclusive, long toIndexExclusive) {
this.from = fromIndexInclusive;
this.to = toIndexExclusive;
}
public Response call() {
int topResultIndex;
double topResult = 0;
for (long i = from; i < to; ++i) {
double result = calculateResult(i);
if (result > topResult) {
topResult = result;
topResultIndex = i;
}
}
Response res = new Response();
res.index = topResultIndex;
res.result = topResult;
return res;
}
};
private static calculateResult(long index) { ... }
public Response interfaceMethod() {
//You might want to make this static/shared/global
ExecutorService svc = Executors.newCachedThreadPool();
int chunks = Runtime.getRuntime().availableProcessors();
long iterations = 1000000000;
MyTask[] tasks = new MyTask[chunks];
for (int i = 0; i < chunks; ++i) {
//You'd better cast to double and round here
tasks[i] = new MyTask(iterations / chunks * i, iterations / chunks * (i + 1));
}
List<Future<Response>> resp = svc.invokeAll(Arrays.asList(tasks));
Iterator<Future<Response>> respIt = resp.iterator();
//You'll have to handle exceptions here
Response bestResponse = respIt.next().get();
while (respIt.hasNext()) {
Response r = respIt.next().get();
if (r.result > bestResponse.result) {
bestResponse = r;
}
}
return bestResponse;
}
Run Code Online (Sandbox Code Playgroud)
根据我的经验,这对块的划分要快得多,因为每个索引都有一个任务(特别是如果每个索引的计算负荷很小,就像它可能的那样.小,我的意思是不到半秒).但是,编码有点困难,因为你需要进行两步最大化(首先是块级,然后是全局级).有了这个,如果计算纯粹是基于cpu的(不会过多地推动ram),你应该获得几乎等于物理核心数量80%的加速.
| 归档时间: |
|
| 查看次数: |
7102 次 |
| 最近记录: |