Java中的for循环并行化

3

我有一个很长的双重嵌套for循环,需要进行多次试验。由于这些试验是相互独立的,因此我希望能够并行处理。我想在Java中高效地实现类似于C++中的OpenMP的功能。我将在拥有64个处理器的节点上运行此程序,所以希望每个核心执行一次测量。

相关代码:

//I want each measure to perform the doubly nested loop at the same time.

for (int i : measures) {

  for (int j = 0; j < N; j++) {
    for (int k = 0; k < N; k++) {
    array[i*N*N + j*N + k] = someFunc(i,j,k);
    }
  }

}

编辑:仍然存在问题:

//sim is a 1D array of type double
//gM is an array of type SMconf
//gene[foo].annot is a LinkedHashSet of URIs.
//Javadoc http://www.semantic-measures-library.org/sml/docs/apidocs/

Arrays.parallelSetAll( sim, i -> {
    try {
        engine.compare( gM[i/(N*N)], gene[(i/N)%N].annot, gene[i % N].annot );
    }
    catch (SLIB_Ex_Critic ex) {
        Logger.getLogger(Exp2.class.getName()).log(Level.SEVERE, null, ex);
    }
});

错误:

这里输入图片描述


(该错误信息无法翻译为具体内容,请提供更多上下文以获取准确翻译)

了解线程:https://docs.oracle.com/javase/tutorial/essential/concurrency/ - Michael
1
你可以尝试使用并行流 - 不过你可能需要更改someFunc的签名,直接接受数组项而不是其在数组中的位置。 - Sva.Mu
2个回答

1
    int N=5;
    int array[]=new int[200];
    int [] measures={1,2,3,4,5};

    Arrays.stream(measures).parallel().forEach(i->{
        IntStream.range(0, N).parallel().forEach(j->{
            IntStream.range(0, N).parallel().forEach(k->{
                array[i*N*N+j*N + k]= someFunc(i,j,k);
            });
        });
    });


    Arrays.stream(array).forEach(System.out::println);

考虑到 measures 是一个数组而不是一个 ArrayList。在写入 array[] 时,您可能希望使用锁定机制。 我希望您没有将 array 作为变量名。


如果 measures 不是一个 int 数组,而是一个 Measure 类的对象数组呢? - henri
如果measures不是整数,那么你的代码for (int i : measures)是如何运行的?另外,在设置array[i*N*N+j*N + k]时为什么要跳过索引? - pallavt
抱歉,我跳过了哪个索引? - henri
array[i*N*N+j*N + k] 中,你正在乘以 N 并加上 kj,因此你必定会跳过一些元素。 - pallavt

0

也许更有效的方法是使用Java-8中的Arrays.parallelSetAll方法:

Arrays.parallelSetAll(array, idx -> someFunc(idx/(N*N), (idx/N)%N, idx % N));

这将并行地独立设置数组元素。虽然您可能会有一些分割的开销,但它很可能比创建嵌套并行流(如 @pallavt 的答案)的开销要小得多。但这可能取决于问题的大小。

如果您的 someFunc 抛出已检查异常,请将其重新抛出为未经检查的异常:

Arrays.parallelSetAll(array, idx -> {
    try {
        return someFunc(idx/(N*N), (idx/N)%N, idx % N);
    }
    catch(MyCheckedException ex) {
        throw new RuntimeException(ex);
    }
});

如果生成器函数抛出异常怎么办?这种情况正在发生,Netbeans 默认生成的 try catch 在 parallelSetall 函数中无法工作。 - henri
@henri,编辑了答案以展示如何处理已检查异常。通常在Java-8中,您应该在任何地方都优先考虑未经检查的异常。 - Tagir Valeev
非常感谢你,Tagir。我再试一次,但它显示“lambda表达式中的错误返回类型,缺少返回值。” - henri
它应该返回一个双精度浮点数。 - henri
@henri,你在try块中漏掉了return语句,而我的代码中有。仔细看一下。 - Tagir Valeev
谢谢Tagir。我添加了返回,但是我仍然得到相同的错误。 :/ - henri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接