运筹系列42:Julia进阶

1. 文件读写

语法和python很像,读文件使用open-readlines-close,写文件使用open-println(file,data)-close
使用DelimitedFiles包中的readlm()读取csv文件。
读文件:
readline读取一行;readlines读取所有行为一个数组;eachline读取为一个迭代器:
在这里插入图片描述
写文件:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 与python/c/Fortran交互

通过PyCall包,Julia可以直接调用Python包。例如:

using PyCall
np= pyimport("numpy")
x = np.linspace(1, 10, 10)

数值、布尔、字符串、IO stream、函数、元组、数组或列表、以及包含这些类型的字典等,它们都会自动进行类型的转换(Python函数会被转换或传递为Julia的函数,反之亦然)。其它类型则是通过通用的PyObject提供的。
下面是调用c函数的例子。

ccall((:clock, "libc"), Int32, ()) # 调用C的clock函数

3. 绘图

在这里插入图片描述

3.1 pyplot

既然都装了python了,就用pyplot绘图吧。

using PyPlot
x=1:10
xlabel("x")
y=ones(10)
for i=1:10
    y[i]=-i*i*i
end
ylabel("y")
title("XKCD plot")
plot(x,y)

另一种方式:

在这里插入图片描述
第三种方式:
在这里插入图片描述

3.2 使用Images

using Images
url = "..."
download(url,"test.jpg")
load("test.jpg")

下载图片,并绘制原图

3.3 skimage

pyplot()
@pyimport skimage.io as io
io.imshow("test.jpg") # 也可以直接放链接

3.4 Plots

using Plots
import FileIO
pyplot()
plot(FileIO.load("test.jpg"))

4. 数学工具

最小二乘拟合:LsqFit包,实现了LM算法
数值微分:Calculus包
数值积分:QuadGK包
自动微分:FowardDiff包
图论:LightGraphs包
OR接口:JuMP包。

下面是个例子,注意下标从1开始,使用Int和Bin表示整数和0-1变量

using JuMP,GLPK
m = Model(GLPK.Optimizer)
@variable(m,0<=x<=2)
@variable(m,0<=y<=2)
@objective(m,Max,5x+3y)
@constraint(m,1x+5y<=3.0)
JuMP.optimize!(m)
println(JuMP.value(x),",",JuMP.value(y),",",JuMP.objective_value(m))

julia中的slice是copy操作,引用操作需要使用view。注意shape也是view操作。

z = view(v,3:5)
# or use macro
z = @views v[3:5]

5. 基准测试

使用@timeit、@time 来做基本的测试
使用

m = randn(1<<16, 8)

function test_swaprow(m::VecOrMat)
    N = size(m, 1)
    for i = 1:N-1
        swaprows!(m, i, i+1)
    end
    m
end

using BenchmarkTools
@benchmark test_swaprow($m)

返回

BenchmarkTools.Trial: 
  memory estimate:  25.97 MiB
  allocs estimate:  653308
  --------------
  minimum time:     12.866 ms (7.65% GC)
  median time:      17.959 ms (8.86% GC)
  mean time:        18.326 ms (10.94% GC)
  maximum time:     27.736 ms (12.75% GC)
  --------------
  samples:          273
  evals/sample:     1
function swaprows!(v::VecOrMat{T}, i::Int, j::Int) where T
    for c = 1:size(v, 2)
        temp = v[i, c]
        v[i, c] = v[j, c]
        v[j, c] = temp
    end
    v
end
@benchmark test_swaprow($m)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     1.459 ms (0.00% GC)
  median time:      1.524 ms (0.00% GC)
  mean time:        1.582 ms (0.00% GC)
  maximum time:     2.926 ms (0.00% GC)
  --------------
  samples:          3147
  evals/sample:     1

6. 模块

模块是一些互相隔离的工作空间,用法上类似于Python中的库。模块中的export是将这函数导出来,这样就可以直接使用。如下:

module mytest
export myAdd

myAdd(x,y)=x+y
end

调用时,先include,然后就可以直接使用了
在这里插入图片描述

7. 宏

使用macro定义宏,然后使用@引用宏。总体来说非常像function
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8 并行计算

8.1 协程/任务

协程也称为任务,如果一个计算以任务的方式执行,那它就很可能会被其他任务中断,原先的任务在恢复后,会从被中断的地方继续工作,这种过程看似很像函数调用,但有两点不同:1)任务切换不需要任何空间,因此可以完成任意数量任务的切换,而且无需考虑堆栈问题。2)任务切换可以按照任何顺序来进行。
任务比较适合生产者-消费者模式,一个过程用来生产值,另一个用来消费值。消费者不能简单的调用生产者来得到值,因为两者的执行时间不一定协同,但是在任务中,两者则可以正常运行。
Julia中提供了Channel来解决生产者消费者的协同问题,其实Channel就是一个FIFO(first-in first-out)队列。使用put!和take!(或是fetch,不删除)函数来具体实现。任务的一个特性就是随着任务的结束,channel对象会自动关闭,无需人为干预。
如果一个 Channel 是空的,读取的 task(即执行 take! 的task)会被阻塞直到有新的数据准备好了;如果一个 Channel 是满的,那么写入的 task(即执行 put! 的 task)则会被阻塞,直到 Channel 有空余。在控制台里面表现为堵塞住,无法继续执行命令
isready 可以用来检查一个 channel 中是否有已经准备好的元素,而等待一个元素准备好 则用 wait。
在这里插入图片描述

Channel也可以接收一个函数,介绍及示例如下:
在这里插入图片描述

在这里插入图片描述
接下来看下任务的调度。用@task定义,然后用schedule进行调度。
在这里插入图片描述

8.2 线程

使用Threads.nthreads()查看当前的线程数,默认是启动一个线程。
使用export JULIA_NUM_THREADS=4(Linux OSX)或set JULIA_NUM_THREADS=4(Windows)来设置启动4个线程。当我们要在Jupyter中使用多个线程时,可以在Julia的运行目录中下打开命令行,先设置线程数,再启动Julia。
在这里插入图片描述
其中Ref和[]分别是取地址和引用。
在这里插入图片描述

8.3 进程

多进程也叫多核心或者分布式处理,就是用一个CPU的多个核心或者多个CPU进行编程。使用julia -p n启动多进程,也可以进入后添加。
在这里插入图片描述

Julia 中的分布式编程基于两个基本概念:远程引用(remote references)和远程调用(remote calls)。远程引用是一个对象,任意一个进程可以通过它访问存储在某个特定进程上的对象。远程调用指是某个进程发起的执行函数的请求,该函数会在另一个(也可能是同一个)进程中执行。

远程引用有两种类型:Future 和 RemoteChannel。

一次远程调用会返回一个 Future 作为结果。
远程调用会立即返回;也就是说,执行远程调用的进程接下来会继续执行下一个操作,而远程调用则会在另外的进程中进行。你可以通过对返回的 Future 执行 wait 操作来等待远程调用结束,然后用 fetch 获取结果。

对于 RemoteChannel 而言,它可以被反复写入。
例如,多个进程可以通过引用同一个远程 Channel 来协调相互之间的操作。

每个进程都有一个对应的 id,提供 Julia 交互环境的进程的 id 永远是1。我们把用来执行并行任务的进程称为 “worker”,假如总共只有一个进程,那么进程1就被认为是 worker,否则,除了进程1以外的进程都称作 worker。
在这里插入图片描述

9. 概率相关

9.1 基本用法

在这里插入图片描述

9.2 综合例子

rand:uniform分布
StatsBase.countmap:统计列表中每个元素的个数,生成一个字典
bar可以直接绘制字典
下面是个综合例子:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值