【问题标题】:Using the stream api of java for a feed forward computation使用java的stream api进行前馈计算
【发布时间】:2018-03-24 20:04:50
【问题描述】:

对于我的一个大学项目,我需要用纯 Java 实现一个深度学习神经网络。在分析应用程序后,我想看看使用 java 的流 api 的自动并行化是否会显着提高性能,但我正在努力将我的旧代码转换为基于流的方法。

该方法接受一个向量(双精度数组),执行矩阵乘法,然后将一个值添加到每个元素,最后将一个 lambda 函数 (DoubleFunction) 应用于每个元素。

这是我要替换的旧代码:

/* e.g.
double[] x = double[100]
int inputNeurons = 100
int outputNeurons = 200
double[][] weights = double[200][100]
double[] biases = double[200]
*/
private double[] output(double[] x) {     
    double[] y = new double[outputNeurons];

    for (int i = 0; i < outputNeurons; i++) {
        double preActivation = 0.;
        for (int j = 0; j < inputNeurons; j++) {
            preActivation += weights[i][j] * x[j];
        }
        preActivation += biases[i];
        y[i] = activation.apply(preActivation);
    }
}

这是我到目前为止想出的(它不起作用):

private double[] output(double[] x) {
    return Arrays.stream(weights).parallel()
            .map(outputNeuron -> IntStream.range(0, outputNeurons)
                    .mapToDouble(i -> IntStream.range(0, inputNeurons)
                            .mapToDouble(j -> x[i] * outputNeuron[i]).sum()
                ).map(activation::apply)
            ).toArray();

由于我对流的了解不够好,我非常感谢任何帮助!

【问题讨论】:

  • 您是否收到错误消息?它到底有什么问题?
  • 目前它的返回类型是java.lang.Object[]
  • return IntStream.range(0, outputNeurons) .mapToDouble(i -&gt; IntStream.range(0, inputNeurons) .mapToDouble(j -&gt; weights[i][j] * x[j]).sum() + biases[i]) .map(activation::apply) .toArray(); 怎么样?
  • @Konstantin 你知道Arrays.stream(weights) 返回一个Stream&lt;double[]&gt;,不认为那是你想要的吗?我之前的评论中与您的命令式方法完全相同。
  • @Konstantin 并行时需要考虑许多因素 :)。

标签: java parallel-processing java-stream


【解决方案1】:

不错的尝试,但您的流式方法与命令式方法完全不同。与您的命令式方法完全相同的是:

return IntStream.range(0, outputNeurons)
                //.parallel() uncomment to see difference in performance
                .mapToDouble(i -> IntStream.range(0, inputNeurons)
                        .mapToDouble(j -> weights[i][j] * x[j]).sum() + biases[i])
                .map(activation::apply)
                .toArray();

请注意,有许多因素会影响并行流是否会使您的代码比命令式方法或顺序流更快或更慢。因此,您需要在并行之前考虑一些因素。

  • 数据大小
  • 核心数
  • 每个元素的成本(意味着并行执行所花费的时间以及分解和合并的开销)

  • 源数据结构

  • 打包(意味着原始类型比装箱值更快)。

你也应该考虑阅读Should I always use a parallel stream when possible?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2020-02-23
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多