Julia - 具有Attribute的Mutable结构,它是一个Function和@code_warntype

JKH*_*KHA 2 performance struct julia

在Julia中,我想要一个带有属性的可变结构,该类型是一个Function,这个函数将有参数:

mutable struct Class_example
    function_with_arguments::Function
    some_attribute::Int
    function Class_example() new() end
    function Class_example(function_wa::Function, some_a::Int)
        this = new()
        this.function_with_arguments = function_wa
        this.some_attribute = some_a
        this
    end
end
Run Code Online (Sandbox Code Playgroud)

我也想对这个可变结构做一个动作:

function do_action_on_class(Class::Class_example)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
Run Code Online (Sandbox Code Playgroud)

然后我定义一个旨在成为我的类属性的函数:

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end
Run Code Online (Sandbox Code Playgroud)

最后,function_whith_arguments将在我的整个项目中启动大量时间,这只是一个最小的例子,所以我希望所有这些代码都非常快.这就是我根据Julia的文档性能提示使用@code_warntype的原因

但是,@ code_warntype告诉我这个

body::Any
15 1 ? %1 = (Base.getfield)(Class, :function_with_arguments)::Function
getproperty
%2 = (Base.getfield)(Class, :some_attribute)::Int64
%3 = (%1)(%2, 2.0, true)::Any                                     ? 
return %3              
Run Code Online (Sandbox Code Playgroud)

在这里,::Function两者::Any都是红色的,表明Julia可以通过更好的实现来提高代码的性能.那么这个正确的实现是什么?我应该如何在我的可变结构中将我的属性function_whith_arguments声明为Function类型?

整码可编辑:

mutable struct Class_example
    function_with_arguments::Function
    some_attribute::Int
    function Class_example() new() end
    function Class_example(function_wa::Function, some_a::Int)
        this = new()
        this.function_with_arguments = function_wa
        this.some_attribute = some_a
        this
    end
end


function do_action_on_class(Class::Class_example)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end

function main()
    class::Class_example = Class_example(do_something_function, 4)
    @code_warntype do_action_on_class(class)
end

main()
Run Code Online (Sandbox Code Playgroud)

crs*_*nbr 5

这将是有效的(很好地推断).请注意,我只修改(并重命名)了该类型.

mutable struct MyClass{F<:Function}
    function_with_arguments::F
    some_attribute::Int
end


function do_action_on_class(Class::MyClass)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end

function main()
    class::MyClass = MyClass(do_something_function, 4)
    @code_warntype do_action_on_class(class)
end

main()
Run Code Online (Sandbox Code Playgroud)

我做了什么?

  • 如果你关心性能,你永远不应该有抽象类型的字段,并且isabstracttype(Function) == true.您应该做的是对该字段类型进行参数化(F上面,可以是任何函数.请注意isconcretetype(typeof(sin)) == true).这样,对于MyCall每个字段的精确具体类型的任何特定实例,在编译时是已知的.

  • 与性能无关但是:不需要只为所有字段分配所有参数的构造函数.隐式地默认定义这样的构造函数.

您可以在此处阅读有关参数类型的更多信息.

另外,你正在做的事情看起来很像试图在朱莉娅中编写OO风格.我建议不要这样做,而是使用Julia方式使用Julia方式使用多个调度.