为什么我的julia代码运行得这么慢?

时间:2016-01-05 15:50:08

标签: performance julia

redim = 2;
# Loading data
iris_data = readdlm("iris_data.csv");
iris_target = readdlm("iris_target.csv");

# Center data
iris_data = broadcast(-, iris_data, mean(iris_data, 1));
n_data, n_dim = size(iris_data);

Sw = zeros(n_dim, n_dim);
Sb = zeros(n_dim, n_dim);

C = cov(iris_data);


classes = unique(iris_target);

for i=1:length(classes)
    index = find(x -> x==classes[i], iris_target);
    d = iris_data[index,:];
    classcov = cov(d);
    Sw += length(index) / n_data .* classcov;
end
Sb = C - Sw;

evals, evecs = eig(Sw, Sb);
w = evecs[:,1:redim];
new_data = iris_data * w;

此代码仅对iris_data执行LDA(线性判别分析)。 将iris_data的尺寸缩小为2。 这将需要大约4秒,但Python(numpy / scipy)只需要大约0.6秒。  为什么呢?

1 个答案:

答案 0 :(得分:12)

这是来自Julia Manual的介绍的第一页,第二段:

  

由于Julia的编译器与用于Python或R等语言的解释器不同,您可能会发现Julia的性能起初并不直观。如果您发现某些内容很慢,我们强烈建议您在尝试其他任何操作之前先阅读 Performance Tips 部分。一旦了解了Julia的工作原理,就可以轻松编写几乎与C一样快的代码。

摘录:

  

避免全局变量

     

全局变量可能具有其值,因此其类型随时都会发生变化。这使编译器难以使用全局变量优化代码。变量应该是本地的,或者尽可能作为参数传递给函数。

     

任何对性能至关重要或正在进行基准测试的代码都应该在函数内部。

     

我们发现全局名称通常是常量,并且声明它们会大大提高性能

知道脚本(所有程序顶级代码)样式在许多科学计算用户中如此普遍,我建议你至少将整个文件包装在let表达式中对于初学者(让我们介绍一个新的本地范围),即:

let

redim = 2
# Loading data
iris_data = readdlm("iris_data.csv")
iris_target = readdlm("iris_target.csv")

# Center data
iris_data = broadcast(-, iris_data, mean(iris_data, 1))
n_data, n_dim = size(iris_data)

Sw = zeros(n_dim, n_dim)
Sb = zeros(n_dim, n_dim)

C = cov(iris_data)


classes = unique(iris_target)

for i=1:length(classes)
    index = find(x -> x==classes[i], iris_target)
    d = iris_data[index,:]
    classcov = cov(d)
    Sw += length(index) / n_data .* classcov
end
Sb = C - Sw

evals, evecs = eig(Sw, Sb)
w = evecs[:,1:redim]
new_data = iris_data * w

end

但是我还会敦促你将它重构为小函数然后组成一个调用其余函数的main函数,像这样,注意这个重构如何使你的代码变得通用和可重用(和快速):< / p>

module LinearDiscriminantAnalysis

export load_data, center_data

"Returns data and target Matrices."
load_data(data_path, target_path) = (readdlm(data_path), readdlm(target_path))

function center_data(data, target)
    data = broadcast(-, data, mean(data, 1))
    n_data, n_dim = size(data)
    Sw = zeros(n_dim, n_dim)
    Sb = zeros(n_dim, n_dim)
    C = cov(data)
    classes = unique(target)
    for i=1:length(classes)
        index = find(x -> x==classes[i], target)
        d = data[index,:]
        classcov = cov(d)
        Sw += length(index) / n_data .* classcov
    end
    Sb = C - Sw
    evals, evecs = eig(Sw, Sb)
    redim = 2
    w = evecs[:,1:redim]
    return data * w
end

end
using LinearDiscriminantAnalysis

function main()
    iris_data, iris_target = load_data("iris_data.csv", "iris_target.csv")
    result = center_data(iris_data, iris_target)
    @show result
end

main()

注意:

  • 你不需要所有这些分号。
  • 匿名函数目前很慢,但会在v0.5中发生变化。如果性能至关重要,您现在可以使用FastAnonymous
  • 总结请仔细阅读并考虑所有的效果提示。
  • main只是一个名字,它可能是你喜欢的任何其他名称。