基于Engee函数的高级块开发
工程项目说明
我们已经学会了如何[使用Engee函数开发我们的块](https://engee.com/community/ru/catalogs/projects/prodvinutoe-ispolzovanie-engee-function )。
但是,如果要实现的算法是复杂和繁琐的呢? 问题立即出现:
*Engee函数代码原来是臃肿的,只是很难阅读。
*目前还不清楚如何测试这样的代码。 如果发生错误,则很难对其进行本地化。
解决这些问题不是"火箭科学",而是程序员的日常工作。 所以让我们成为他们一段时间!
这就是我们将如何解决繁琐代码的问题。:
-
让我们将算法分离成一个单独的模块
-
我们将用测试复盖模块
-
让我们增加代码的稳定性
作为一个例子,考虑一种算法,用于查找两组观测值之间的距离。 为了工作,我们需要以下软件包:
import Pkg
Pkg.add(["LinearAlgebra", "Test", "BenchmarkTools"])
;cat PDIST2.jl
测试
测试的目的是证明代码工作正常,并且捕获所有异常。
测试是用[测试]编写的。jl]包(https://engee.com/helpcenter/stable/ru/julia/stdlib/Test.html )
让我们创建三个简单的测试:
*简单的函数调用
*不同尺寸的加工
*计算相同矩阵之间距离的正确性
让我们把这些测试放在一个测试套件中,它被定义为:
``'茱莉亚
@testset
<测试>
结束
测试包中测试的一个特殊功能。Jl是测试宏验证某个表达式的真实性。 我们来看一个例子:
using Test, LinearAlgebra
demoroot = @__DIR__
include("PDIST2.jl")
X = rand(3,3)
Y = rand(3,3)
Z = PDIST2.EF_pdist2(X,Y);
@testset "EF_pdist2 tests" begin
@test_nowarn PDIST2.EF_pdist2(X,Y);
@test_throws DimensionMismatch PDIST2.EF_pdist2(rand(3,3),rand(2,2))
@test iszero(diag(PDIST2.EF_pdist2(X,X)))
end
工作表现评估
要评估代码的整体性能,您需要测量几个指标:
*执行速度
*分配的内存量
*分配数量(特定于Julia)
为此,我们将使用基准。jl包。 它的优点在于您可以微调实验或立即开始测量。:
using BenchmarkTools
@benchmark PDIST2.EF_pdist2(rand(10,10),rand(10,10))
以下测量对我们很重要:时间和内存估计。
时间是单次运行的执行时间。 由于@benchmark运行了几次运行,我们得到了一组这样的测量值,并且可以对其应用统计处理。 运行@benchmark宏后显示其结果,如上所示。
内存估计将显示分配的内存量。 让我们看看执行时间和内存量是如何随着输入量的增加而增加的。:
matrix_size = 80 # @param {type:"slider",min:10,max:100,step:10}
@benchmark PDIST2.EF_pdist2(rand(matrix_size,matrix_size),rand(matrix_size,matrix_size))
容错能力
您创建的代码必须具有抗错误性。 这需要处理异常。
一般意义上的异常是可以处理的任何错误。 与通常的错误(语法错误)的主要区别在于用户可以自己生成异常。 让我们来看看我们的pdist2函数的代码:
``'茱莉亚
m,n=尺寸(X)
p,n2=尺寸(Y)
n==n2||throw(DimensionMismatch("X和Y中的列数必须匹配"))
如果矩阵的维度不匹配,则调用throw函数并抛出异常。
异常可以使用构造来处理
``'茱莉亚
试试
渔获
结束
代码调用被放置在try块中。 如果此代码引发异常,则将执行catch块中的代码。
在Engee函数中使用库
例如,我们将使用EF_dist_find模型。:
mdl = engee.open(joinpath(demoroot,"EF_dist_find.engee"));
考虑PDIST2块构造函数:
``'茱莉亚
include("/user/start/examples/base_simulation/advanced_block_development/PDIST2.jl")
可变结构块<:AbstractCausalComponent
缓存:矩阵{Float64};
功能块()
c=零(Float64,INPUT_SIGNAL_ATTRIBUTES[1]。尺寸);
info("分配$(Base.summarysize(c))字节为pdist2")
新(c)
结束
结束
我们将我们的模块包含在Engee函数中,指定其代码的完整路径。
使用##info()##函数,我们将显示创建缓存时分配的内存量。
考虑此块的步骤方法:
``'茱莉亚
函数(c::块)(t::实,in1,in2)
试试
c.缓存=PDIST2。EF_pdist2(in1,in2);
渔获
错误("矩阵维度应该相等!")
停止模拟()
结束
返回c.缓存
结束
请注意,来自我们模块的函数调用被包装在异常处理程序中。 如果我们的pdist2函数抛出异常,则错误"矩阵维数应该相等!"将出现在诊断窗口中,模拟将停止。
打开时,创建两个带有随机数的3x3矩阵。 让我们确保模型工作。:
engee.run(mdl)
结论
该项目展示了一种创建基于Engee函数的块的方法,这使得调试更容易,并提高了代码的质量和可靠性。