Optimization 朱莉娅:如何模仿一些;typedef/using";我们在C++;(而且没有性能处罚)?

Optimization 朱莉娅:如何模仿一些;typedef/using";我们在C++;(而且没有性能处罚)?,optimization,types,julia,Optimization,Types,Julia,基本上,我想在struct a中提供一些类型信息,稍后将使用这些信息定义foo_1函数的返回类型 以下是我迄今为止掌握的Julia代码: struct A type::DataType end foo_1(a::A)::a.type = 2018 用法示例: julia> a=A(Float64) julia> foo_1(a) 2018.0 ->这项工作如预期的那样:2018年被转换为a.typetype,这里是aFloat64 然而,我的问题/疑问来自这样一个事实:

基本上,我想在
struct a
中提供一些类型信息,稍后将使用这些信息定义
foo_1
函数的返回类型

以下是我迄今为止掌握的Julia代码:

struct A
    type::DataType
end

foo_1(a::A)::a.type = 2018
用法示例:

julia> a=A(Float64)
julia> foo_1(a)
2018.0
->这项工作如预期的那样:2018年被转换为
a.type
type,这里是a
Float64

然而,我的问题/疑问来自这样一个事实:当与函数
foo_2
相比时,该函数在不使用
x.type

foo_2(a::A)::Float64 = 2018
生成的代码中有一个重要的差异:

julia> @code_native foo_2(a)
    .text
Filename: REPL[4]
    pushq   %rbp
    movq    %rsp, %rbp
    movabsq $139943184603960, %rax  # imm = 0x7F470FCE9B38
Source line: 1
    movsd   (%rax), %xmm0           # xmm0 = mem[0],zero
    popq    %rbp
    retq
    nopw    %cs:(%rax,%rax)
->这没关系

但是对于
foo_1(a::a)::a.type
函数:

julia> @code_native foo_1(a)
    .text
Filename: REPL[3]
    pushq   %rbp
    movq    %rsp, %rbp
    pushq   %r15
    pushq   %r14
    pushq   %rbx
    subq    $56, %rsp
    movq    %rdi, %r14
    movq    %fs:0, %r15
    addq    $-10888, %r15           # imm = 0xD578
    leaq    -48(%rbp), %rdi
    xorps   %xmm0, %xmm0
    movups  %xmm0, -48(%rbp)
    movq    $0, -32(%rbp)
    movq    $8, -72(%rbp)
    movq    (%r15), %rax
    movq    %rax, -64(%rbp)
    leaq    -72(%rbp), %rax
    movq    %rax, (%r15)
    movq    $0, -56(%rbp)
Source line: 1
    movq    (%r14), %rax
    movabsq $139943153507008, %rcx  # imm = 0x7F470DF41AC0
    leaq    634701288(%rcx), %rdx
    movq    %rdx, -48(%rbp)
    movq    %rax, -40(%rbp)
    movq    %rcx, -32(%rbp)
    movabsq $jl_apply_generic, %rax
    movl    $3, %esi
    callq   *%rax
    movq    %rax, %rbx
    movq    %rbx, -56(%rbp)
    movq    (%r14), %rsi
    movabsq $jl_typeassert, %rax
    movq    %rbx, %rdi
    callq   *%rax
    movq    -64(%rbp), %rax
    movq    %rax, (%r15)
    movq    %rbx, %rax
    addq    $56, %rsp
    popq    %rbx
    popq    %r14
    popq    %r15
    popq    %rbp
    retq
->我很惊讶Julia JIT无法生成优化的函数。IMHO it在呼叫站点
foo_1(a)
上拥有执行此操作所需的所有信息

-->我担心生成的代码差异太大,如果我使用
a.type
的方法,我的性能会很差

所以我的问题是:

    >P>1,是否有更好的朱丽亚定义类型信息的方法(我在思考<代码> TyPulf< /Calp+C++等价)

  • 2/如何解释foo_1(a)和foo_2(a)之间生成的代码差异

    ->到目前为止,我的解释是:like foo_1不是一个参数函数,Julia只生成一个函数实例,因此它必须动态地解析类型(即使结构a是不可变的)。我说得对吗


注意:我本来可以写

struct B{T}
end

foo_3{T}(b::B{T})::T  = 2018
这是可行的(从某种意义上说,
foo_3
的本机代码与
foo_2
相同),但是这是一个难以定义几种类型的解决方案:

struct B{T1,T2,T3,...}
end
在没有“寄生虫”模板参数的情况下,C++等价物是:

struct B {
    using T1 = ...;
    using T2 = ...;
    using T3 = ...;
    ...
};

关键是Julia不知道什么类型的
A.type
不仅仅是一些
数据类型。可以使用参数化类型提供以下信息:

julia> struct A{T}
           typ::Type{T}
       end
       foo_1(a::A)::a.typ = 2018
foo_1 (generic function with 1 method)

julia> foo_1(A(Float64))
2018.0

julia> @code_native foo_1(A(Float64))
    .section    __TEXT,__text,regular,pure_instructions
; Function foo_1 {
; Location: REPL[9]:5
    movabsq $4572864984, %rax       ## imm = 0x1109061D8
    movsd   (%rax), %xmm0           ## xmm0 = mem[0],zero
    retq
    nop
;}

foo_1和foo_2之间的区别在于,在foo_2中,编译器知道编译时的最终游戏是什么,而在foo_1中,它必须从参数的值中找出它。它只能在运行时知道参数的值。您可以使用“笨拙”参数化类型检查包。谢谢,我同意您的回答。然而,我仍然有点失望:请参阅“structb{T}end”部分,我的文章的末尾。如果我有几个类型,我必须定义一个{T1,T2等}。如果我想添加一个类型,我必须更改一个{}签名(通过添加一个类型)。Julia根据其在每个函数中接收的对象类型进行专门化。在第一个示例中,Julia只知道它有一个
A
类型的对象,
A.typ
可以是任何
数据类型。所以它必须动态地查找它。它工作得很好;只是没你想的那么快。解决方案是将
typ
信息提升到参数中的外部结构。你是对的,这实际上与上一个例子相同。我误解了你的抱怨。