Julia:如何模仿我们在C++中使用的一些"typedef/using"(并且没有性能惩罚)?



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

这是我到目前为止拥有的朱莉娅代码:

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类型,这里是Float64

但是,我的问题/询问来自这样一个事实,即与不使用x.type的功能foo_2相比,

函数基本相同
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

-> 我很惊讶朱莉娅 JIT 无法生成优化的功能。恕我直言,它在呼叫站点foo_1(a)拥有所有必需的信息。

-->我担心生成的代码差异太大,如果我将该方法与a.type一起使用,我会得到糟糕的性能。

所以我的问题是:

  • 1/有没有更好的 Julia 方法来定义类型信息(我正在考虑typedefC++等效的)

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

    -> 到目前为止我的解释:我认为像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 = ...;
...
};

关键很简单,朱莉娅不知道A.type是什么类型,除了它只是一些DataType。 您可以使用参数化类型来提供此信息:

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
;}

最新更新