在Java中转换Matlab程序以提高性能的敏感性

时间:2014-01-15 19:41:44

标签: java matlab genetic-algorithm sudoku

我有一个有点假设的问题。作为计算智能课程项目的一部分,我们刚刚编写了一些实现遗传算法的代码,以找到数独游戏的解决方案。不幸的是,它运行速度非常慢,这限制了我们执行足够数量运行以找到最佳参数的能力。问题在于重新编程整个事物 - 代码基础并不是那么大 - 将java作为提高软件速度的可行解决方案。就像我们真正需要10倍的性能提升一样,我怀疑Java版本会如此迅速。有什么想法吗?

谢谢

===更新1 ===

这是计算上最昂贵的函数的代码。它是一个GA适应度函数,它遍历总体(不同的数独板)并计算每一行和每列有多少元素是重复的。参数n被传递,并且当前设置为9.也就是说,该函数计算一行中有多少元素在1到9的范围内出现,然后再多出一次。数字越大,董事会的适应性就越低,这意味着它对下一代来说是一个弱势候选人。

分析器报告在for循环中调用两行的行导致性能不佳,但我们不知道如何真正优化代码。它如下:

function [fitness, finished,d, threshold]=fitness(population_, n)
finished=false;
threshold=false;
V=ones(n,1);
d=zeros(size(population_,2),1);
s=[1:1:n];
for z=1:size(population_,2)
    board=population_{z};
    t=0;
    l=0;
    for i=1:n
        l=l+n-length(intersect(s,board(:,i)'));
        t=t+n-length(intersect(s,board(i,:)));

    end
    k=sum(abs(board*V-t));

    f=t+l+k/50;
    if t==2 &&l==2
        threshold=true;
    end
    if f==0
        finished=true;        
    else
        fitness(z)=1/f;
        d(z)=f;
    end
end
end

===更新2 ===

在此处找到解决方案:http://www.mathworks.com/matlabcentral/answers/112771-how-to-optimize-the-following-function

使用histc(V,1:9),速度要快得多:)

4 个答案:

答案 0 :(得分:1)

如果不查看代码,知道是否使用并行化等,这是不可能的。事实上,正如MrAzzaman所说,分析是首先要做的事情。如果您发现单个瓶颈,特别是如果它是循环沉重的,那么将该部分写入C并通过MEX将其连接到Matlab可能就足够了。

在遗传学算法中,我认为可以获得10倍的速度提升而不是。我不太同意MrAzzaman - 在某些情况下(for循环,使用动态对象)比C / C ++ / Java慢得多。这并不是说Matlab总是很慢,因为它不是,但是有很多算法会很慢。

即,我会说,如果你不花太多时间在事物上循环,不使用对象,不受Matlab的数据结构的限制,你可以使用Matlab。也就是说,如果我要用Java或Matlab编写GAs,我宁愿选择前者(而且我现在使用Matlab比Java更多,这不仅仅是习惯问题)。

顺便说一下。如果您不想自己编程,请查看JGAP,它对于GA来说是一个非常有用的Java库。

答案 1 :(得分:1)

好的,第一步就是编写更快的MATLAB函数。保存新语言以供日后使用。

我将假设董事会充满了有效的猜测:也就是说,每个条目都在[1,9]中。现在,我们真正想要的是每行/每列中的重复条目。为了找到重复,我们排序。在排序的行上,如果任何元素等于其邻居,则我们有重复。在MATLAB中,diff函数执行滑动成对差分,其输出中的零表示两个相邻值相等。 sort和diff都在整个矩阵上运行,因此不需要循环。这是列式检查的代码:

l=sum(sum(diff(sort(board)) == 0));

行方向检查完全相同,只是使用转置。现在让我们把它放在测试工具中,将结果和时间与以前的版本进行比较:

n = 9;
% Generate a test board.  Random integers numbers from 1:n
board = randi(n, n);

s = 1:n;
K=1000; % number of iterations to use for timing

% Repeat current code for comparison
tic
for k=1:K
    t=0;
    l=0;
    for i=1:n
        l=l+n-length(intersect(s,board(:,i)'));
        t=t+n-length(intersect(s,board(i,:)));
    end
end
toc

% New code based on sort/diff for finding repeated values
tic
for k=1:K
    l2=sum(sum(diff(sort(board)) == 0));
    t2=sum(sum(diff(sort(board.')) == 0));
end
toc

% Check that reported values match
disp([l l2])
disp([t t2])

我建议您分解sort / diff / sum代码,并在命令行的示例board上构建它,并尝试准确理解它是如何工作的。

在我的系统上,新代码的速度提高了约330倍。

答案 2 :(得分:0)

对于用于学习和研究目的的传统GA应用程序,最好使用本机编译的源代码编程语言,如C,C ++。我在使用Genetic时使用过的 在过去的编程,它真的很快。

但是,如果您计划将其置于更现代的应用程序类型中,该应用程序可以部署在Web容器中,也可以在移动设备,不同的操作系统等中运行。那么Java是您的最佳选择,因为它与平台无关。

另一件重要的事情是关于并发性。例如,让我们假设您希望将GA放在Internet中,并且您将拥有越来越多的并发连接的用户,并且所有用户都希望解决不同的数据,Java应用程序非常适合水平扩展并且工作得很好具有大量并发连接。

如果迁移到Java,那么可能有用的其他方面是可以使用的库和框架的数量,Java Universe非常大,几乎可以为任何类型的应用程序找到有用的工具。

Java是一种虚拟机编译语言,但重要的是要注意当前JVM在性能方面非常出色并且能够优化程序,例如,他们会发现哪些方法使用得更频繁并将它们编译为本机代码,这意味着对于某些应用程序,您会发现Java程序几乎与从C编译的本机程序相同。

Matlab是一个非常适用于工程训练和数学,矢量,基于矩阵的计算的平台,也适用于Simulink的一些控件。我在电气工程学士学位时使用过这些产品,但是这些产品的目标主要是用于学术目的的工具,如果我想为现实世界构建生产应用程序,我绝对不会选择Matlab。它不具有可扩展性,维护和微调的成本很高,而且还没有很多基础设施提供商支持这种技术。

关于将代码重写为Java的复杂性,Matlab代码和Java代码语法非常相似,它们也存在于相同的范例中:程序OOP,即使您在代码中没有使用OO,也可以轻松地重写在Java中,当使用Matlab快捷方式来处理数学结构(如矩阵和传递函数作为参数)时,会遇到一些痛苦的事情。

对于矩阵的东西,有很多像EJML这样的java库会让你的生活更轻松。关于将函数赋值给变量然后将它们作为参数传递给另一个函数,Java目前无法做到这一点(Java 8将使用Lambda表达式),但是您可以通过使用类闭包来获得等效的功能。也许这些将是你在迁移时会发现的唯一一些痛苦的事情。

答案 3 :(得分:0)

在此处找到解决方案:http://www.mathworks.com/matlabcentral/answers/112771-how-to-optimize-the-following-function

使用histc(V,1:9),速度要快得多:)