这是在 Julia 中将整数转换为字节数组的最快方法
Which is the fastest way to convert an integer to a byte array in Julia
问题1:Which是将整数转换为字节数组的最快方法吗?
a = 1026
aHexStr = string(a,base = 16,pad = 4) #2 bytes, 4 chars
b = zeros(UInt8,2)
k = 1
for i in 1:2:4
b[k] = parse(UInt8,aHexStr[i:i+1],base = 16)
k += 1
end
这个方法最快吗?
相关问题二:
将十六进制字符串转换为字节数组的最快方法是什么?
我有一串十六进制数
a = "ABCDEF12345678"
How can I convert this hex string to byte array?
b = zeros(UInt8,7)
k = 1
for i in 1:2:14
b[k] = parse(UInt8,a[i:i+1],base = 16)
k += 1
end
这个方法最快吗?
对于第一个操作,我假设您只想保留整数中设置的字节数,因此您可以这样做:
julia> a = 1026
1026
julia> [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
2-element Vector{UInt8}:
0x02
0x04
解释:
leading_zeros(a)
获取 a
以 开头的零位数
leading_zeros(a)>>3
计算完全为空的字节数(>>3
将数字右移 3
位;在本例中为底除以 8)
sizeof(a)-leading_zeros(a)>>3
计算要转换的字节数
(i-1)<<3)
计算我们需要移动索引的位数(在本例中是 i-1
乘以 8)
(a>>((i-1)<<3))%UInt8
获取 a
的第 i-1
个字节
对于第二个操作,我假设如果你有奇数个字符,我们确实用 0 位填充最后一个字节的剩余部分 + 我们不需要检查传递的数据是否有效:
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> s2b(a)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
两种方法都应该很快,但很难保证它们最快。
编辑
基准:
julia> function f1(a)
aHexStr = string(a,base = 16,pad = 4) #2 bytes, 4 chars
b = zeros(UInt8,2)
k = 1
for i in 1:2:4
b[k] = parse(UInt8,aHexStr[i:i+1],base = 16)
k += 1
end
return b
end
f1 (generic function with 1 method)
julia> f2(a) = [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
f2 (generic function with 1 method)
julia> using BenchmarkTools
julia> a = 1026
1026
julia> @btime f1($a)
141.795 ns (5 allocations: 224 bytes)
2-element Vector{UInt8}:
0x04
0x02
julia> @btime f2($a)
29.317 ns (1 allocation: 64 bytes)
2-element Vector{UInt8}:
0x02
0x04
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> @btime hex2bytes($a)
50.000 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
julia> @btime s2b($a)
48.830 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
正如@SundarR 在后一种情况下评论的那样,应该使用 hex2bytes
。我忘了它的存在。
对于第一个问题,您可以 reinterpret
字节,如果您可以使用额外的 0 值:reinterpret(UInt8, [a])
。
这比 Bogumił Kamiński 的答案中的代码执行速度稍快,大约快 5-10% - 但相差几纳秒。所以如果额外的 0 很麻烦,那可能不值得。
编辑:您可以删除多余的零,方法如下:
julia> bytesfromint(i::Int64) =
@inbounds @view reinterpret(UInt8, [i])[1:8-leading_zeros(i)>>3]
这似乎也比 Bogumil Kaminsky 的回答中提到的方法快了 20% 左右。
@inbounds @view reinterpret(UInt8, [ai])[(8-leading_zeros(ai)>>3):-1:1]
将首先为您提供最重要的字节(类似大端),或者 @inbounds @view reinterpret(UInt8, [ai])[2:-1:1]
如果您知道您的数据将只占用 2 个字节。
(@view
告诉 Julia 不要复制我们要求的数组部分,而是索引到原始数组本身——从而避免复制开销。@inbounds
确保Julia,我们的索引在数组的边界内——因此避免了边界检查开销。)
问题1:Which是将整数转换为字节数组的最快方法吗?
a = 1026
aHexStr = string(a,base = 16,pad = 4) #2 bytes, 4 chars
b = zeros(UInt8,2)
k = 1
for i in 1:2:4
b[k] = parse(UInt8,aHexStr[i:i+1],base = 16)
k += 1
end
这个方法最快吗?
相关问题二: 将十六进制字符串转换为字节数组的最快方法是什么?
我有一串十六进制数
a = "ABCDEF12345678"
How can I convert this hex string to byte array?
b = zeros(UInt8,7)
k = 1
for i in 1:2:14
b[k] = parse(UInt8,a[i:i+1],base = 16)
k += 1
end
这个方法最快吗?
对于第一个操作,我假设您只想保留整数中设置的字节数,因此您可以这样做:
julia> a = 1026
1026
julia> [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
2-element Vector{UInt8}:
0x02
0x04
解释:
leading_zeros(a)
获取a
以 开头的零位数
leading_zeros(a)>>3
计算完全为空的字节数(>>3
将数字右移3
位;在本例中为底除以 8)sizeof(a)-leading_zeros(a)>>3
计算要转换的字节数(i-1)<<3)
计算我们需要移动索引的位数(在本例中是i-1
乘以 8)(a>>((i-1)<<3))%UInt8
获取a
的第
i-1
个字节
对于第二个操作,我假设如果你有奇数个字符,我们确实用 0 位填充最后一个字节的剩余部分 + 我们不需要检查传递的数据是否有效:
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> s2b(a)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
两种方法都应该很快,但很难保证它们最快。
编辑
基准:
julia> function f1(a)
aHexStr = string(a,base = 16,pad = 4) #2 bytes, 4 chars
b = zeros(UInt8,2)
k = 1
for i in 1:2:4
b[k] = parse(UInt8,aHexStr[i:i+1],base = 16)
k += 1
end
return b
end
f1 (generic function with 1 method)
julia> f2(a) = [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
f2 (generic function with 1 method)
julia> using BenchmarkTools
julia> a = 1026
1026
julia> @btime f1($a)
141.795 ns (5 allocations: 224 bytes)
2-element Vector{UInt8}:
0x04
0x02
julia> @btime f2($a)
29.317 ns (1 allocation: 64 bytes)
2-element Vector{UInt8}:
0x02
0x04
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> @btime hex2bytes($a)
50.000 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
julia> @btime s2b($a)
48.830 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
正如@SundarR 在后一种情况下评论的那样,应该使用 hex2bytes
。我忘了它的存在。
对于第一个问题,您可以 reinterpret
字节,如果您可以使用额外的 0 值:reinterpret(UInt8, [a])
。
这比 Bogumił Kamiński 的答案中的代码执行速度稍快,大约快 5-10% - 但相差几纳秒。所以如果额外的 0 很麻烦,那可能不值得。
编辑:您可以删除多余的零,方法如下:
julia> bytesfromint(i::Int64) =
@inbounds @view reinterpret(UInt8, [i])[1:8-leading_zeros(i)>>3]
这似乎也比 Bogumil Kaminsky 的回答中提到的方法快了 20% 左右。
@inbounds @view reinterpret(UInt8, [ai])[(8-leading_zeros(ai)>>3):-1:1]
将首先为您提供最重要的字节(类似大端),或者 @inbounds @view reinterpret(UInt8, [ai])[2:-1:1]
如果您知道您的数据将只占用 2 个字节。
(@view
告诉 Julia 不要复制我们要求的数组部分,而是索引到原始数组本身——从而避免复制开销。@inbounds
确保Julia,我们的索引在数组的边界内——因此避免了边界检查开销。)