基本上,我想在 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/