简介
Julia 是一个面向科学计算的高性能动态高级程序设计语言。其语法与其他科学计算语言相似。在许多情况下拥有能与编译型语言相媲美的性能。Julia 是个灵活的动态语言,适合科学和数值计算,性能可与传统静态类型语言媲美。
引用自百度百科.
Julia下的深度学习应用,以及其与Matlab、PyTorch的对比,请参考本人另外一篇博客Julia深度学习
安装与配置
Windows下下载安装包,双击按照提示安装即可,注意选择添加到环境变量. Linux下下载压缩包,解压然后添加环境变量即可. 以Ubuntu系统为例, 从官网下载Linux下的压缩包Generic Linux on x86, 下载下来的文件类似于 julia-1.7.2-linux-x86_64.tar.gz
, 将其放到想安装的目录(记为JULIA_HOME
), 执行命令tar -xzvf julia-1.7.2-linux-x86_64.tar.gz
解压.
输入gedit ~/.bashrc
在PATH
环境变量中添加值JULIA_HOME/julia-1.7.2/bin/
. 重新打开一个终端, 输入julia
, 则可以进入下图所示交互式解释器(REPL)界面
至此安装完成!
包的管理
安装与删除包
- 安装包(方式1): 在REPL界面输入
import Pkg; Pkg.add("XXX")
- 安装包(方式2): 在REPL界面按]键进入包管理器界面, 输入
add XXX
安装 - 删除包(方式1): 在REPL界面输入
import Pkg; Pkg.rm("XXX")
- 删除包(方式2): 在REPL界面按]键进入包管理器界面, 输入
rm XXX
(移除)
导入和使用包,略有不同, 如下图
# 方式一
import Plots
Plots.plot
# 方式二
using Plots
plot
设置代理与更换镜像
如果你需要设置代理才能上网, 则需要为Julia设置代理, 打开~/.julia/config/startup.jl
文件(不存在则新建), 添加如下代码,重启Julia的REPL
ENV["HTTP_PROXY"]="http://xxx:port"
如果发现下载安装包比较慢, 则需要为Julia设置新的镜像, 打开~/.julia/config/startup.jl
文件(不存在则新建), 添加如下代码,重启Julia的REPL
ENV["JULIA_PKG_SERVER"]="https://mirrors.bfsu.edu.cn/julia/"
# ENV["JULIA_PKG_SERVER"]="https://mirrors.tuna.tsinghua.edu.cn/julia"
离线安装包
离线安装包需要在能够联网的机器上,从GitHub上下载包, 具体包的地址,可以根据包的名称到这里查看. 在安装第三方包前,需要先安装General, 通过 git clone https://github.com/JuliaRegistries/General.git
下载General仓库, 放到任意位置, 进入General所在根目录, 在该目录下打开终端,进入Julia的REPL, 然后键入 ]进入包管理器界面.
接着输入 registry add General
来安装, 执行完成后可以在用户目录(~/.julia/registries/
)下看到General.
(@v1.7) pkg> registry add General
Cloning registry from "/home/liu/General"
Added registry `General` to `~/.julia/registries/General`
下面以安装用于读写.mat
的库为例, 从这里可以看到其依赖以下库: BufferedStreams, HDF5, SparseArrays, LinearAlgebra, Libz, CodecZlib
由于依赖较多, 而且每个依赖又会依赖其它包, 故这里通过非离线方式安装MAT的依赖包,然后以离线方式安装MAT包. 在GitHub中搜索相应的包名, clone 带有 .jl
后缀的, 比如 MAT.jl
, 在克隆的MAT.jl
的根目录进入Julia的REPL, 按]进入管理界面, 然后输入 add .MAT.jl
即可, 安装完成, 通过 using MAT
即可使用其中的函数, 如 matread
, matwrite
等等, 如下.
性能测试
- 硬件测试环境
- CPU:
Intel® Xeon(R) E5-2696 v3
- 内存:
62.8 GiB
- CPU:
- 软件测试环境
- 系统:
Ubuntu16.04LTS
- 语言版本:
Matlab2020, Python3.6, Julia-1.7.2,
- 系统:
话不多说,直接上代码与测试结果.
矩阵乘法代码如下
矩阵求逆代码如下
FFT代码如下
需要注意的是:Julia中FFTW库中的fft函数, 如果不指定维度, 则默认对所有维进行傅里叶变换, 测试结果如下表(单位s)
算法 | Matlab | Python | Julia |
---|---|---|---|
乘法( 10240 × 10240 , N i t e r = 10 10240\times 10240, N_{\rm iter}=10 10240×10240,Niter=10) | 51.5664 | 68.0704 | 78.2974 |
求逆( 10240 × 10240 , N i t e r = 10 10240\times 10240, N_{\rm iter}=10 10240×10240,Niter=10) | 100.5972 | 142.6631 | 152.7482 |
乘法( 1024 × 1024 , N i t e r = 1000 1024\times 1024, N_{\rm iter}=1000 1024×1024,Niter=1000) | 6.3905 | 9.0961 | 9.5913 |
求逆( 1024 × 1024 , N i t e r = 1000 1024\times 1024, N_{\rm iter}=1000 1024×1024,Niter=1000) | 21.9986 | 47.6916 | 25.6484 |
FFT( 1024 × 1024 , N i t e r = 1000 1024\times 1024, N_{\rm iter}=1000 1024×1024,Niter=1000) | 1.9614 | 39.6829 | 39.9219 |
FFT( 512 × 512 , N i t e r = 1000 512\times 512, N_{\rm iter}=1000 512×512,Niter=1000) | 0.8779 | 9.4411 | 7.2179 |
FFT( 1024 × 128 , N i t e r = 1000 1024\times 128, N_{\rm iter}=1000 1024×128,Niter=1000) | 0.4734 | 4.2433 | 2.6365 |
FFT( 128 × 1024 , N i t e r = 1000 128\times 1024, N_{\rm iter}=1000 128×1024,Niter=1000) | 0.8079 | 4.1781 | 3.1636 |
FFT( 512 × 128 , N i t e r = 1000 512\times 128, N_{\rm iter}=1000 512×128,Niter=1000) | 0.2515 | 2.3216 | 1.3724 |
FFT( 128 × 512 , N i t e r = 1000 128\times 512, N_{\rm iter}=1000 128×512,Niter=1000) | 0.4383 | 2.3234 | 1.6585 |
运行效率平稳性分析
上一小节评估了不同语言的平均运行性能,下面看下单次运行效率.
Windows下的硬件环境:
- CPU:
Intel m3-6Y30@0.90GHz 1.51GHz
- RAM:
4GB
Ubuntu下的硬件环境:
- CPU:
Intel E5-2696 v3 @ 2.30GHz × 36
- RAM:
64GB
实验代码
FFT
from time import time
import numpy as np
from numpy.fft import fft
M, N = 2048, 2048
Niter = 300
x = np.random.rand(M, N) + 1j * np.random.rand(M, N)
tstart = time()
for n in range(Niter):
t1 = time()
y = fft(fft(x, axis=0), axis=1)
t2 = time()
print('---Iter: %d, time: %.4f ms' % (n, (t2 - t1) * 1000))
tend = time()
print('---Total time: %.4f s' % (tend - tstart))
M = 2048; N = 2048;
Niter = 300;
x = rand(M, N) + 1j * rand(M, N);
tstart = tic;
for n = 1:Niter
t1 = tic;
y = fft(fft(x, [], 1), [], 2);
t2 = toc(t1);
fprintf('---Iter: %d, time: %.4f ms\n', n, t2 * 1000)
end
tend = toc(tstart);
fprintf('---Total time: %.4f s\n', tend)
using FFTW
using Printf
FFTW.set_provider!("mkl")
FFTW.set_num_threads(18)
M, N = 2048, 2048
Niter = 300
x = rand(M, N) + im * rand(M, N)
tstart = time()
for n = 1:Niter
t1 = time()
y = fft(fft(x, 1), 2)
t2 = time()
@printf("---Iter: %d, time: %.4f ms\n", n, (t2 - t1)*1000)
end
tend = time()
@printf("---Total time: %.4f s\n", tend - tstart)
加噪
from time import time
import numpy as np
f = 100
Fs = 800
Ts = 50.
Ns = int(Fs * Ts)
Nsnr = 61
SNRs = np.linspace(-30., 30., Nsnr)
Nk = 300
t = np.linspace(-Ts / 2., Ts / 2., Ns)
x = np.sin(2. * np.pi * f * t)
def noising(x, SNR):
linearSNR = 10**(SNR / 10.)
n = np.random.randn(*x.shape)
Es = np.sum(x**2)
En = np.sum(n**2)
α = np.sqrt(Es / linearSNR / En)
noise = α * n
y = x + noise
return y, noise
def calsnr(y, n):
snrv = np.sum(y**2) / np.sum(n**2)
return 10 * np.log10(snrv)
tstart = time()
for k in range(Nk):
t1 = time()
for SNR in SNRs:
y, n = noising(x, SNR)
snrv = calsnr(y, n)
t2 = time()
print('---Iter: %d, snr: %.2f, time: %.4f ms' % (k, snrv, (t2 -t1) * 1000))
tend = time()
print('---Total time: %.4f s' % (tend - tstart))
f = 100;
Fs = 800;
Ts = 50.;
Ns = uint32(Fs*Ts);
Nsnr = 61;
SNRs = linspace(-30., 30., Nsnr);
Nk = 300;
t = linspace(-Ts / 2., Ts / 2., Ns);
x = sin(2. * pi * f * t);
global snrv;
tstart = tic;
for k = 1:Nk
t1 = tic;
for i =1:Nsnr
[y, n] = noising(x, SNRs(i));
snrv = calsnr(y, n);
end
t2 = toc(t1);
fprintf('---Iter: %d, snr: %.2f, time: %.4f ms\n', k, snrv, t2 * 1000);
end
tend = toc(tstart);
fprintf('---Total time: %.4f s\n', tend);
function [y, noise] = noising(x, SNR)
linearSNR = 10^(SNR / 10.);
n = randn(size(x));
Es = sum(x.^2);
En = sum(n.^2);
alpha = sqrt(Es / linearSNR / En);
noise = alpha * n;
y = x + noise;
end
function [snrv] = calsnr(y, n)
snrv = sum(y.^2) / sum(n.^2);
snrv = 10 * log10(snrv);
end
using Printf
f = 100
Fs = 800
Ts = 50.
Ns = Int(Fs * Ts)
Nsnr = 61
SNRs = LinRange(-30., 30., Nsnr)
Nk = 300
t = LinRange(-Ts / 2., Ts / 2., Ns)
x = sin.(2. * pi * f * t)
function noising(x, SNR)
linearSNR = 10^(SNR / 10.)
n = randn(size(x))
Es = sum(x.^2)
En = sum(n.^2)
α = sqrt(Es / linearSNR / En)
noise = α * n
y = x + noise
return y, noise
end
function calsnr(y, n)
snrv = sum(y.^2) / sum(n.^2)
return 10 * log10(snrv)
end
tstart = time()
for k =1:Nk
t1 = time()
for SNR in SNRs
y, n = noising(x, SNR)
global snrv = calsnr(y, n)
end
t2 = time()
@printf("---Iter: %d, snr: %.2f, time: %.4f ms\n", k, snrv, (t2- t1)*1000)
end
tend = time()
@printf("---Total time: %.4f s\n", tend - tstart)
实验结果
分别运行上述程序3次,将每次输出时间信息保存到log文件,如windows_fft_python_1.log
, ubuntu_noise_julia_3.log
, 使用下述代码绘制散点图. Julia和Python通过vscode运行.
import numpy as np
import pyaibox as pb
import matplotlib.pyplot as plt
os = 'windows'
os = 'ubuntu'
nshots = 300
nrow, ncol = 1, 3
plt.figure()
iters = np.linspace(1, nshots, nshots)
for n in range(1, nrow*ncol+1):
tpy = pb.readnum('./%s_noise_python_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
tma = pb.readnum('./%s_noise_matlab_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
tju = pb.readnum('./%s_noise_julia_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
plt.subplot(nrow, ncol, n)
plt.grid()
plt.scatter(iters, tpy)
plt.scatter(iters, tma)
plt.scatter(iters, tju)
plt.legend(['Python', 'Matlab', 'Julia'])
plt.title(n)
plt.show()
nshots = 300
nrow, ncol = 1, 3
plt.figure()
iters = np.linspace(1, nshots, nshots)
for n in range(1, nrow*ncol+1):
tpy = pb.readnum('./%s_fft_python_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
tma = pb.readnum('./%s_fft_matlab_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
tju = pb.readnum('./%s_fft_julia_%d.log' % (os, n), 'Iter', 'time: ', float, nshots)
plt.subplot(nrow, ncol, n)
plt.grid()
plt.scatter(iters, tpy)
plt.scatter(iters, tma)
plt.scatter(iters, tju)
plt.legend(['Python', 'Matlab', 'Julia'])
plt.title(n)
plt.show()
Windows 10
FFT 结果(纵轴:时间(ms), 横轴:迭代次数)
加噪声结果(纵轴:时间(ms), 横轴:迭代次数)
Ubuntu 16.04 LTS
FFT 结果(纵轴:时间(ms), 横轴:迭代次数)
加噪声结果(纵轴:时间(ms), 横轴:迭代次数)