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

Performance 为什么我的julia代码运行得这么慢?,performance,julia,Performance,Julia,该代码仅对iris_数据进行LDA(线性判别分析)。 将iris_数据的维数减少到2。 这大约需要4秒,但是Python(numpy/scipy)只需要0.6秒。 为什么?这是从介绍的第一页第二段开始的: 由于Julia的编译器与Python或R等语言使用的解释器不同,您可能会发现Julia的性能起初并不直观。如果您发现速度较慢,我们强烈建议您在尝试其他操作之前先阅读部分。一旦您了解了Julia的工作原理,就很容易编写速度接近C的代码 摘录: 避免全局变量 全局变量的值和类型可能会在任何时候发

该代码仅对iris_数据进行LDA(线性判别分析)。 将iris_数据的维数减少到2。 这大约需要4秒,但是Python(numpy/scipy)只需要0.6秒。
为什么?

这是从介绍的第一页第二段开始的:

由于Julia的编译器与Python或R等语言使用的解释器不同,您可能会发现Julia的性能起初并不直观。如果您发现速度较慢,我们强烈建议您在尝试其他操作之前先阅读部分。一旦您了解了Julia的工作原理,就很容易编写速度接近C的代码


摘录:

避免全局变量 全局变量的值和类型可能会在任何时候发生变化。这使得编译器很难使用全局变量优化代码。变量应该是局部变量,或者尽可能作为参数传递给函数

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

我们发现全局名称通常是常量,将它们声明为常量可以极大地提高性能


知道脚本(全过程顶级代码)风格在许多科学计算用户中非常普遍,我建议您至少将整个文件包装在一个
let
表达式中(让它引入一个新的局部范围),即:

let
redim=2
#加载数据
iris_data=readdlm(“iris_data.csv”)
iris_target=readdlm(“iris_target.csv”)
#中心数据
iris_数据=广播(-,iris_数据,平均值(iris_数据,1))
n_数据,n_dim=大小(虹膜数据)
Sw=零(n_尺寸,n_尺寸)
Sb=零(n_dim,n_dim)
C=cov(iris_数据)
类别=唯一(iris\U目标)
对于i=1:长度(类)
索引=查找(x->x==类[i],iris\U目标)
d=iris_数据[索引:]
classcov=cov(d)
Sw+=长度(索引)/n_数据。*类别COV
结束
Sb=C-Sw
评估,evecs=eig(西南、西南)
w=evecs[:,1:redim]
新数据=虹膜数据*w
结束
但我也建议您将其重构为小函数,然后编写一个调用其余函数的
main
函数,类似这样,请注意此重构如何使您的代码具有通用性和可重用性(以及快速性):

模块线性描述分析
导出加载数据、中心数据
“返回数据和目标矩阵。”
加载数据(数据路径,目标路径)=(readdlm(数据路径),readdlm(目标路径))
功能中心_数据(数据、目标)
数据=广播(-,数据,平均值(数据,1))
n_数据,n_尺寸=大小(数据)
Sw=零(n_尺寸,n_尺寸)
Sb=零(n_dim,n_dim)
C=cov(数据)
类别=唯一(目标)
对于i=1:长度(类)
索引=查找(x->x==类[i],目标)
d=数据[索引:]
classcov=cov(d)
Sw+=长度(索引)/n_数据。*类别COV
结束
Sb=C-Sw
评估,evecs=eig(西南、西南)
redim=2
w=evecs[:,1:redim]
返回数据*w
结束
结束

使用线性描述分析
函数main()
iris_数据,iris_目标=加载_数据(“iris_data.csv”,“iris_target.csv”)
结果=中心数据(虹膜数据、虹膜目标)
@显示结果
结束
main()
注:


  • 你不需要所有的分号
  • 匿名函数目前速度较慢,但在v0.5中会有所改变。如果性能至关重要,您现在可以使用
  • 总之,仔细阅读并考虑所有性能提示
  • main
    只是一个名称,可以是您喜欢的任何其他名称

值得一读。你不需要所有的分号
main
函数和使用
let
块之间有什么区别,还是仅仅是“最佳实践”?将一些变量声明为
const
怎么样,比如
iris\u data
?考虑到“脚本风格在许多科学计算用户中非常普遍”,我经常发现自己将要计算的数据声明为
const
:p非常感谢!不同之处在于,这确实是最佳实践!:D将全局变量声明为
const
也会起作用,但随后您就失去了使用模块和函数将代码与n个不同数据集重用的模块性(对于测试、分析和基准测试非常有用,而不会陷入其中),
center_data
的功能不应该也不应该依赖于
iris_data.csv
&
iris_target.csv
。例如,这些只是提供给函数的参数,使其可重复使用而不是一次性使用。
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;