用于转置double [] []矩阵的紧凑流表达式 [英] Compact stream expression for transposing double[][] Matrix

查看:116
本文介绍了用于转置double [] []矩阵的紧凑流表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用最紧凑和最有效的表达式转换 double [] [] 矩阵。现在我有这个:

I want to tranpose a double[][] matrix with the most compact and efficient expression possible. Right now I have this:

public static Function<double[][], double[][]> transpose() {
    return (m) -> {
        final int rows = m.length;
        final int columns = m[0].length;
        double[][] transpose = new double[columns][rows];
        range(0, rows).forEach(r -> {
            range(0, columns).forEach(c -> {
                transpose[c][r] = m[r][c];
            });
        });
        return transpose;
    };
}

想法?

推荐答案

你可能有:

public static UnaryOperator<double[][]> transpose() {
    return m -> {
        return range(0, m[0].length).mapToObj(r ->
            range(0, m.length).mapToDouble(c -> m[c][r]).toArray()
        ).toArray(double[][]::new);
    };
}

此代码不使用 forEach 但更喜欢 mapToObj mapToDouble ,用于将每一行映射到它们的转置。我还将功能< double [] [],双[] []> 更改为 UnaryOperator< double [] []> 因为返回类型是相同的。

This code does not use forEach but prefers mapToObj and mapToDouble for mapping each row to their transposition. I also changed Function<double[][], double[][]> to UnaryOperator<double[][]> since the return type is the same.

然而,像assylias 的回答。

示例代码:

public static void main(String[] args) {
    double[][] m = { { 2, 3 }, { 1, 2 }, { -1, 1 } };
    double[][] tm = transpose().apply(m);
    System.out.println(Arrays.deepToString(tm)); // prints [[2.0, 1.0, -1.0], [3.0, 2.0, 1.0]]
}






我已经实现了一个JMH基准测试,比较上面的代码,for循环版本,以及上面的代码并行运行。使用大小为100,1000和3000的随机平方矩阵调用所有三种方法。结果是对于小矩阵,循环版本的更快但具有更大的矩阵并行流式解决方案在性能方面确实更好( Windows 10,JDK 1.8.0_66,i5-3230M @ 2.60 GHz ):

Benchmark                           (matrixSize)  Mode  Cnt    Score    Error  Units
StreamTest.forLoopTranspose                  100  avgt   30    0,026 ±  0,001  ms/op
StreamTest.forLoopTranspose                 1000  avgt   30   14,653 ±  0,205  ms/op
StreamTest.forLoopTranspose                 3000  avgt   30  222,212 ± 11,449  ms/op
StreamTest.parallelStreamTranspose           100  avgt   30    0,113 ±  0,007  ms/op
StreamTest.parallelStreamTranspose          1000  avgt   30    7,960 ±  0,207  ms/op
StreamTest.parallelStreamTranspose          3000  avgt   30  122,587 ±  7,100  ms/op
StreamTest.streamTranspose                   100  avgt   30    0,040 ±  0,003  ms/op
StreamTest.streamTranspose                  1000  avgt   30   14,059 ±  0,444  ms/op
StreamTest.streamTranspose                  3000  avgt   30  216,741 ±  5,738  ms/op

基准代码:

@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(3)
public class StreamTest {

    private static final UnaryOperator<double[][]> streamTranspose() {
        return m -> {
            return range(0, m[0].length).mapToObj(r ->
                range(0, m.length).mapToDouble(c -> m[c][r]).toArray()
            ).toArray(double[][]::new);
        };
    }

    private static final UnaryOperator<double[][]> parallelStreamTranspose() {
        return m -> {
            return range(0, m[0].length).parallel().mapToObj(r ->
                range(0, m.length).parallel().mapToDouble(c -> m[c][r]).toArray()
            ).toArray(double[][]::new);
        };
    }

    private static final Function<double[][], double[][]> forLoopTranspose() {
        return m -> {
            final int rows = m.length;
            final int columns = m[0].length;
            double[][] transpose = new double[columns][rows];
            for (int r = 0; r < rows; r++)
                  for (int c = 0; c < columns; c++)
                    transpose[c][r] = m[r][c];
            return transpose;
        };
    }

    @State(Scope.Benchmark)
    public static class MatrixContainer {

        @Param({ "100", "1000", "3000" })
        private int matrixSize;

        private double[][] matrix;

        @Setup(Level.Iteration)
        public void setUp() {
            ThreadLocalRandom random = ThreadLocalRandom.current();
            matrix = random.doubles(matrixSize).mapToObj(i -> random.doubles(matrixSize).toArray()).toArray(double[][]::new);
        }

    }

    @Benchmark
    public double[][] streamTranspose(MatrixContainer c) {
        return streamTranspose().apply(c.matrix);
    }

    @Benchmark
    public double[][] parallelStreamTranspose(MatrixContainer c) {
        return parallelStreamTranspose().apply(c.matrix);
    }

    @Benchmark
    public double[][] forLoopTranspose(MatrixContainer c) {
        return forLoopTranspose().apply(c.matrix);
    }

}

这篇关于用于转置double [] []矩阵的紧凑流表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆