高效地将Java列表转换为Matlab矩阵

4

我正在从Matlab调用Google Protocol Buffers Java API。这个过程进行得相当顺利,但是我遇到了一个性能瓶颈。大部分数据以以下类型的对象返回:

java.util.Collections$UnmodifiableRandomAccessList

实际上它们包含了一系列浮点数。我需要将其转换为Matlab矩阵。目前我发现的最佳方法是调用:

cell2mat(cell(Q.toArray()))

然而,在该代码中,那一行成为了巨大的性能瓶颈。
请注意,我知道FarSounder Matlab解析生成器用于Google Protocol Buffers,但不幸的是,它们非常慢。如下所示是我的问题的一些粗略基准速度(YMMV),速度越快越好:
- Farsounder Matlab:0.03 - 纯Python:1 - 从Matlab调用的Java API(仅解析和提取元数据):10 - 从Matlab调用的Java API(解析和提取元数据和数据):0.25
如果不考虑将java.util.Collections$UnmodifiableRandomAccessList转换为Matlab矩阵的开销,那么从Matlab调用Java API的方法将显得非常有前途。 是否有更好的方法将此Java对象转换为Matlab矩阵? 请记住,返回此类型的方法位于自动生成的代码中。

1
我的建议是尽可能减少调用MATLAB-Java桥的次数。例如,如果您从MATLAB循环内部调用Java代码,请在Java代码中收集所有输出,然后从MATLAB进行单个方法调用。您能否分享一些最小化的代码供我们测试(我知道Java代码是自动生成的)? - Amro
2个回答

7

您最好编写一小段额外的Java代码,就像这样:

import java.util.List;
import java.util.ListIterator;

class Helper {
    public static float[] toFloatArray(List l) {
        float retValue[] = new float[l.size()];
        ListIterator iterator = l.listIterator();
        for (int idx = 0; idx < retValue.length; ++idx ){
            // List had better contain float values,
            // or else the following line will ClassCastException.
            retValue[idx] = (float) iterator.next();
        }
        return retValue;
    }
}

我能够看到的:

>> j = java.util.LinkedList;
>> for idx = 1:1e5, j.add(single(idx)); end
>> tic, out = Helper.toFloatArray(j); toc
Elapsed time is 0.006553 seconds.
>> tic, cell2mat(cell(j.toArray)); toc
Elapsed time is 0.305973 seconds.

这个工作完美无缺。使用这种方法,基准速度从0.25现在增加到了6。这使得从Matlab调用JAVA API成为我迄今尝试过的最快的方法。恐怕我没有足够的声望点来赞同这个答案。 - Andrew McLean

1
根据我的经验,最高效的解决方案是编写一组小的Java帮助程序,将列表转换为原始类型的纯数组。这些数组可以很好地映射到Matlab中的矩阵。例如,如果上述操作返回一个java.lang.Float数组,则该帮助程序可能如下所示:
public static float[] toFloats(Float[] floats) {
    float[] rv = new float[floats.length];
    for (int i=0; i < floats.length; i++) rv[i] = (float) floats[i];
    return rv;
}

在Matlab中,cell2mat(cell(Q.toArray())) 将会变成:
some.package.toFloats(Q.toArray());

显然,您可以修改辅助函数直接获取您的列表,避免需要调用toArray()(这实际上是否会创建一个副本)。

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