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

标签 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.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

-> 我很惊讶 Julia JIT 无法生成优化的函数。恕我直言,它在调用站点 foo_1(a) 上拥有执行此操作所需的所有信息。

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

所以我的问题是:

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

  • 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 的 native 代码与 foo_2 相同),但是,对于定义多种类型来说,这是一个尴尬的解决方案:

struct B{T1,T2,T3,...}
end

C++ 等效项是,没有“寄生虫”模板参数:

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

最佳答案

关键在于 Julia 不知道 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
;}

关于optimization - Julia:如何模仿我们在 C++ 中使用的一些 "typedef/using"(并且没有性能损失)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48458845/

相关文章:

visual-studio-2010 - Visual Studio 2010 优化和技巧?

arrays - 在 Julia 中将数组拆分为训练集和测试集的有效方法是什么?

Haskell 数据类型列表

java - 这行Java代码在做什么?

debugging - Julia IDE 调试

performance - 更符合人类逻辑的源代码是否会产生更优化的编译代码?

c - 快速逐字节替换 if

mysql - 高非小数价格的数据类型

list - 在 Julia 中(解压缩)数组的正确方法

julia - 在 Julia 中何时使用 `!`( bool 非)与 `~`(按位非)?