从部件构建 Vector{UInt8} 时减少内存分配
Reducing memory allocations when building Vector{UInt8} from parts
我希望从不同的部分构建一个 Vector{UInt8},如下所示:
using BenchmarkTools
using Random
const a = Vector{UInt8}("Number 1: ")
const b = Vector{UInt8}(", Number 2: ")
const c = Vector{UInt8}(", Number 3: ")
const d = Vector{UInt8}(", Number 4: ")
function main(num2, num4)::Vector{UInt8}
return vcat(
a,
Vector{UInt8}(string(rand(1:100))),
b,
Vector{UInt8}(string(num2)),
c,
Vector{UInt8}(string(rand(1:100))),
d,
Vector{UInt8}(string(num4)),
)
end
@btime main(70.45, 12) # 486.224 ns (13 allocations: 1.22 KiB)
#Example output: "Number 1: 50, Number 2: 70.45, Number 3: 10, Number 4: 12"
先转字符串再转Vector{UInt8}好像不对。我不介意加入向量时发生的 1 分配。
将整数转换为 UInt8
格式的数字向量可以非常高效地完成。转换浮点数有点棘手。
总而言之,我认为你的代码已经相当高效了。这是加速整数代码的建议。浮点数代码,我没能改进:
function tobytes(x::Integer)
N = ndigits(x)
out = Vector{UInt8}(undef, N)
for i in N:-1:1
(x, r) = divrem(x, 0x0a)
out[i] = UInt8(r) + 0x30
end
return out
end
tobytes(x) = Vector{UInt8}(string(x))
# notice that we generate random UInt8 values instead of rand(1:100), as this is faster. They still have to be converted according to the character interpretation, though.
function main2(num2, num4)
[a; tobytes(rand(0x01:0x64)); b; tobytes(num2); c; tobytes(rand(0x01:0x64)); d; tobytes(num4)]
end
tobytes
for intergers 现在接近最优,运行时间主要由预分配 Vector{UInt8}
.
的时间决定
我希望从不同的部分构建一个 Vector{UInt8},如下所示:
using BenchmarkTools
using Random
const a = Vector{UInt8}("Number 1: ")
const b = Vector{UInt8}(", Number 2: ")
const c = Vector{UInt8}(", Number 3: ")
const d = Vector{UInt8}(", Number 4: ")
function main(num2, num4)::Vector{UInt8}
return vcat(
a,
Vector{UInt8}(string(rand(1:100))),
b,
Vector{UInt8}(string(num2)),
c,
Vector{UInt8}(string(rand(1:100))),
d,
Vector{UInt8}(string(num4)),
)
end
@btime main(70.45, 12) # 486.224 ns (13 allocations: 1.22 KiB)
#Example output: "Number 1: 50, Number 2: 70.45, Number 3: 10, Number 4: 12"
先转字符串再转Vector{UInt8}好像不对。我不介意加入向量时发生的 1 分配。
将整数转换为 UInt8
格式的数字向量可以非常高效地完成。转换浮点数有点棘手。
总而言之,我认为你的代码已经相当高效了。这是加速整数代码的建议。浮点数代码,我没能改进:
function tobytes(x::Integer)
N = ndigits(x)
out = Vector{UInt8}(undef, N)
for i in N:-1:1
(x, r) = divrem(x, 0x0a)
out[i] = UInt8(r) + 0x30
end
return out
end
tobytes(x) = Vector{UInt8}(string(x))
# notice that we generate random UInt8 values instead of rand(1:100), as this is faster. They still have to be converted according to the character interpretation, though.
function main2(num2, num4)
[a; tobytes(rand(0x01:0x64)); b; tobytes(num2); c; tobytes(rand(0x01:0x64)); d; tobytes(num4)]
end
tobytes
for intergers 现在接近最优,运行时间主要由预分配 Vector{UInt8}
.