Ma *_*boi 8 python arrays performance dictionary julia
我正在尝试用 Python 完成一项非常简单的任务,我已经在 Julia 中完成了这项任务。它包括获取多个 3d 元素的数组,并创建该列表中唯一值的索引字典(请注意,该列表有 6,000,000 个元素长)。我已经在 Julia 中完成了此操作,并且速度相当快(6 秒) - 这是代码:
function unique_ids(itr)
#create dictionnary where keys have type of whatever itr is
d = Dict{eltype(itr), Vector}()
#iterate through values in itr
for (index,val) in enumerate(itr)
#check if the dictionary
if haskey(d, val)
push!(d[val],index)
else
#add value of itr if its not in v yet
d[val] = [index]
end
end
return collect(values(d))
end
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。然而,当我尝试在 Python 中执行此操作时,它似乎需要很长时间,以至于我什至无法告诉你需要多长时间。所以问题是,我在这里做了一些愚蠢的事情,还是这只是这两种语言之间差异的现实?这是我的 Python 代码,是 Julia 代码的翻译。
def unique_ids(row_list):
d = {}
for (index,val) in tqdm(enumerate(row_list)):
if str(val) in d:
d[str(val)].extend([index])
else:
d[str(val)] = [index]
return list(d.values())
Run Code Online (Sandbox Code Playgroud)
请注意,我在 Python 中使用字符串作为字典的键,因为在 Python 中不可能将数组作为键。
python 比较慢,只是没有作者想象的那么慢,用优化的代码来展示这一点:
| 语言 | 时间(秒) |
|---|---|
| python 3.11 | 4.6 |
| cpython + Numba (Jit) | 3.3 |
| 朱莉娅1.8.5 | 1.9 |
python 在此仅慢 2.5 倍,当 numba 混合时仅慢 1.5 倍,因此如果您需要最后一点性能,请使用 julia,但 python 在其他方面会获胜,例如编译为轻量级可执行文件或拥有更多用于通用非数值编程的库。
仅优化 python 代码:
import random
from collections import defaultdict
input_list_len = 6_000_000
rand_max = 100
row_list = []
for _ in range(input_list_len):
row_list.append(tuple(random.randint(0,rand_max) for x in range(3)))
def unique_ids(row_list):
d = defaultdict(list)
for (index,val) in enumerate(row_list):
d[val].append(index)
return list(d.values())
import time
t1 = time.time()
output = unique_ids(row_list)
t2 = time.time()
print(f"total time = {t2-t1}")
Run Code Online (Sandbox Code Playgroud)
优化的 numba LLVM jit 代码
import random
import numba
from numba.typed.typedlist import List
from numba.typed.typeddict import Dict
import numba.types
input_list_len = 6_000_000
rand_max = 100
@numba.njit
def generate_list():
row_list = List()
for _ in range(input_list_len):
a = random.randint(0,rand_max)
b = random.randint(0,rand_max)
c = random.randint(0,rand_max)
row_list.append((a,b,c))
return row_list
row_list = generate_list()
@numba.njit("ListType(ListType(int64))(ListType(UniTuple(int64,3)))")
def unique_ids(row_list):
d = Dict()
for (index,val) in enumerate(row_list):
if val in d:
d[val].append(index)
else:
a = List()
a.append(index)
d[val] = a
return List(d.values())
import time
t1 = time.time()
output = unique_ids(row_list)
t2 = time.time()
print(f"total time = {t2-t1}")
Run Code Online (Sandbox Code Playgroud)
优化的朱莉娅代码
using Random
Random.seed!(3);
input_list_len = 6_000_000
rand_max = 100
data::Vector{Tuple{Int64,Int64,Int64}} = Vector{Tuple{Int64,Int64,Int64}}()
for _ in 1:input_list_len
push!(data, Tuple{Int64,Int64,Int64}(rand(0:rand_max,3)))
end
function unique_ids(itr)
#create dictionnary where keys have type of whatever itr is
d = Dict{eltype(itr), Vector{Int}}()
#iterate through values in itr
for (index,val) in enumerate(itr)
#check if the dictionary
if haskey(d, val)
push!(d[val],index);
else
#add value of itr if its not in v yet
d[val] = [index]
end
end
return collect(values(d))
end
@time unique_ids(data);
@time unique_ids(data);
Run Code Online (Sandbox Code Playgroud)