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;
    }
}
对于每个索引,计算完全独立,不共享资源.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;
}
根据我的经验,这对块的划分要快得多,因为每个索引都有一个任务(特别是如果每个索引的计算负荷很小,就像它可能的那样.小,我的意思是不到半秒).但是,编码有点困难,因为你需要进行两步最大化(首先是块级,然后是全局级).有了这个,如果计算纯粹是基于cpu的(不会过多地推动ram),你应该获得几乎等于物理核心数量80%的加速.
| 归档时间: | 
 | 
| 查看次数: | 7102 次 | 
| 最近记录: |