我是一个新手,刚开始接触Julia,并且听说它有惊人的性能。但我还没有体验到那些承诺的性能。我尝试了许多增强性能的方法,这些方法在《JULIA HIGH PERFORMANCE》一书中有描述,但这使得代码的可读性稍微降低了一点。但是,至少在基准测试案例中,我的Python代码比我的Julia代码快3倍以上。
要么是我的代码做错了什么,在Julia中犯了罪,要么就是Julia无法胜任。请证明后者是错误的。
在代码中,我正在尝试将不同的球分配到不同的盒子中,并且每个盒子的容量都有最大和最小限制。放置球的顺序也很重要。我需要在最短的时间内生成所有可能的分配,并满足给定的约束条件。
PYTHON CODE:
以下是我尝试编写上述内容的JULIA代码:
我的基准测试时间如下:
对于Python:
对于Julia语言:(这是在不考虑编译时间的情况下。)
在代码中,我正在尝试将不同的球分配到不同的盒子中,并且每个盒子的容量都有最大和最小限制。放置球的顺序也很重要。我需要在最短的时间内生成所有可能的分配,并满足给定的约束条件。
PYTHON CODE:
import itertools
import time
max_balls = 5
min_balls = 0
def get_assignments(balls, boxes, assignments=[[]]):
all_assignments = []
upper_ball_limit = len(balls)
if upper_ball_limit > max_balls:
upper_ball_limit = max_balls
n_boxes = len(boxes)
lower_ball_limit = len(balls) - upper_ball_limit * (n_boxes - 1)
if lower_ball_limit < min_balls:
lower_ball_limit = min_balls
if len(boxes) == 0:
raise Exception("No delivery boys found")
elif len(boxes) == 1:
for strategy in itertools.permutations(balls, upper_ball_limit):
# valid = evaluate_strategy(strategy, db_id)
for subplan in assignments:
subplan_copy = subplan[:]
box_id = boxes[0]
subplan_copy.append((box_id, strategy))
all_assignments.append(subplan_copy)
return all_assignments
else:
box_id = boxes[0]
for i in range(lower_ball_limit, upper_ball_limit+ 1):
for strategy in itertools.permutations(balls, i):
temp_plans = []
for subplan in assignments:
subplan_copy = subplan[:]
subplan_copy.append((box_id, strategy))
temp_plans.append(subplan_copy)
remaining_balls = set(balls).difference(strategy)
remaining_boxes = list(set(boxes).difference([box_id]))
if remaining_balls:
all_assignments.extend(get_assignments(remaining_balls, remaining_boxes, temp_plans))
else:
all_assignments.extend(temp_plans)
return all_assignments
balls = range(1, 9)
boxes = [1, 2, 3, 4]
t = time.time()
all_assignments = get_assignments(balls, boxes)
print('Number of assignments: %s' % len(all_assignments))
print('Time taken: %s' % (time.time()-t))
以下是我尝试编写上述内容的JULIA代码:
#!/usr/bin/env julia
using Combinatorics
const max_balls=5
const min_balls=0
function plan_assignments(balls::Vector{Int32}, boxes ; plans=[Vector{Tuple{Int32,Array{Int32,1}}}(length(boxes))])
const n_boxes = length(boxes)
const n_balls = length(balls)
const n_plans = length(plans)
if n_boxes*max_balls < n_balls
print("Invalid Inputs: Number of balls exceed the number of boxes.")
end
all_plans = Vector{Tuple{Int32,Array{Int32,1}}}[]
upper_box_limit = n_balls
if upper_box_limit > max_balls
upper_box_limit = max_balls
end
lower_box_limit = n_balls - upper_box_limit * (n_boxes-1)
if lower_box_limit < min_balls
lower_box_limit = min_balls
end
if n_boxes == 1
box_id = boxes[1]
@inbounds for strategy in Combinatorics.permutations(balls, upper_box_limit)
@inbounds for subplan in plans
subplan = subplan[:]
subplan[tn_boxes - n_boxes + 1] = (box_id, strategy)
all_plans = push!(all_plans, subplan)
end
end
return all_plans
else
box_id = boxes[1]
@inbounds for i in lower_box_limit:upper_box_limit
@inbounds for strategy in Combinatorics.permutations(balls, i)
temp_plans = Array{Vector{Tuple{Int32,Array{Int32,1}}},1}(n_plans)
# temp_plans = []
@inbounds for (i,subplan) in zip(1:n_plans, plans)
subplan = subplan[:]
subplan[tn_boxes - n_boxes + 1] = (box_id, strategy)
temp_plans[i] = subplan
# subplan = push!(subplan, (db_id, strategy))
# temp_plans = push!(temp_plans, subplan)
remaining_balls = filter((x) -> !(x in strategy), balls)
remaining_boxes = filter((x) -> x != box_id , boxes)
if length(remaining_balls) > 0
@inbounds for plan in plan_assignments(remaining_balls, remaining_boxes, plans=temp_plans)
push!(all_plans, plan)
end
# append!(all_plans, plan_assignments(remaining_orders, remaining_delivery_boys, plans=temp_plans))
else
@inbounds for plan in temp_plans
push!(all_plans, plan)
end
# append!(all_plans, temp_plans)
end
end
end
end
return all_plans
end
end
balls = Int32[1,2,3,4,5,6,7,8]
boxes = Int32[1,2,3,4]
const tn_boxes = length(boxes)
@timev all_plans = plan_assignments(balls, boxes)
print(length(all_plans))
我的基准测试时间如下:
对于Python:
Number of assignments: 5040000
Time taken: 22.5003659725
对于Julia语言:(这是在不考虑编译时间的情况下。)
76.986338 seconds (122.94 M allocations: 5.793 GB, 77.01% gc time)
elapsed time (ns): 76986338257
gc time (ns): 59287603693
bytes allocated: 6220111360
pool allocs: 122932049
non-pool GC allocs:10587
malloc() calls: 11
realloc() calls: 18
GC pauses: 270
full collections: 28
subplan = subplan[:]
中复制 subplan 吗? - Alexander Morley@code_warntype
的输出是什么?您能够使用ProfileView
显示瓶颈在哪里吗? - Chris Rackauckas