나는 대학에서 프로젝트를위한 기계 학습을 보여주는 그래픽 응용 프로그램을 코딩하려고 노력해 왔으며 파이썬으로 개발 해왔다. 파이썬은 꽤 느린 언어이기 때문에 런타임 실행 속도를 높이고 Cython을 우연히 발견했습니다. 아직 C/C++에 익숙하지 않지만 가능한 한 많은 코드를 정적으로 입력하려고했습니다. 경고가 있어도 가독성/유연성이 떨어질 수 있지만 현재로서는이 점이 제게 큰 문제는 아닙니다.Cython으로 성능 향상 극대화
그러나 필자는 순수한 Python에 비해이 구현을 크게 개선 한 것을 발견하지 못했으며, 속도를 높이는 방법에 대한 제안이 있다면 궁금합니다. 얼마나 현실적인지 모르겠지만 10 배속 향상과 같은 것에 매우 만족할 것입니다.
나는 ̶h̶a̶v̶e̶n̶'̶t̶ 프로파일 내 코드 아직 내 코드를 프로파일 링 한 결과는 다음과 연결되어 있습니다.
아직 진행 중이므로 레이아웃은 좋지 않지만 몇 가지 간단한 기능 그룹화를 수행했습니다.
소스 코드는 here입니다. 코드의 가장 관련성이 높은 부분은 아래에 게시됩니다.
.
주어진 패드의 메모리를 통해 반복하는 :
cdef findBestApproximation(int padindex):
cdef double last_collision_x
cdef double last_collision_y
cdef double last_collision_i_angle
cdef double last_collision_i_speed
cdef double last_collision_f_angle
cdef double last_collision_f_speed
cdef double x_divergence
cdef double y_divergenve
cdef double f_angular_divergence
cdef double divergence
printData("FINDING APPROXIMATION FOR PAD %s...\n" % padindex)
pad = Pads.padlist[padindex]
memory = pad.memory
ball = Balls.ball
if not memory:
approximation = getPadMidpoint(padindex)
return approximation
collision_data = getCollisionData()
(last_collision_x, last_collision_y, last_collision_i_angle,
last_collision_i_speed, last_collision_f_angle,
last_collision_f_speed) = collision_data
best_approx = 0
strictness_coef = 1.03
for memory_tuple in memory:
(x_miss, y_miss, x_collision, y_collision, _, _, f_angle, _) = memory_tuple.getData()
(divergence, x_divergence, y_divergence, f_angular_divergence) = calculateDivergence(memory_tuple, collision_data)
divergence = x_divergence + y_divergence + f_angular_divergence
approximation = (divergence, x_miss, y_miss)
printData("\n\nPAD: %s" % padindex)
printData("\nLAST COLLISION (X) = %s, CONSIDERED CASE (X) = %s" % (last_collision_x, x_collision))
printData("pos_x DIVERGENCE: %s" % x_divergence)
printData("\nLAST COLLISION (Y) = %s, CONSIDERED CASE (Y) = %s" % (last_collision_y, y_collision))
printData("pos_y DIVERGENCE: %s" % y_divergence)
printData("\nLAST COLLISION (fAngle) = %s, CONSIDERED CASE (fAngle) = %s" % (last_collision_f_angle, f_angle))
printData("FINAL ANGLE DIVERGENCE: %s" % f_angular_divergence)
printData("\nTOTAL DIVERGENCE: %s\n\n" % divergence)
if not best_approx:
best_approx = approximation
else:
(least_divergence, _, _) = best_approx
if divergence < least_divergence:
best_approx = approximation
(_, pos_x, pos_y) = best_approx
approximation = (pos_x, pos_y)
return approximation
합니다.
계산 및 패드의 메모리에 저장된 특정 과거 사건에 대한 점수를 돌리는 :
cdef calculateDivergence(memory_tuple, collision_data):
cdef double pos_x_dif
cdef double pos_y_dif
cdef double i_angle_dif
cdef double i_speed_dif
cdef double f_angle_dif
cdef double f_speed_dif
cdef double max_x_difference
cdef double max_y_difference
cdef double max_angular_difference
cdef double x_divergence
cdef double y_divergence
cdef double f_angular_divergence
cdef double total_divergence
(last_collision_x, last_collision_y, last_collision_i_angle,
last_collision_i_speed, last_collision_f_angle,
last_collision_f_speed) = collision_data
(x_miss, y_miss, x_collision, y_collision,
i_angle, i_speed, f_angle, f_speed ) = memory_tuple.getData()
pos_x_dif = abs(x_collision - last_collision_x)
pos_y_dif = abs(y_collision - last_collision_y)
i_angle_dif = getAngleDifference(i_angle, last_collision_i_angle)
i_speed_dif = abs(i_speed - last_collision_i_speed)
f_angle_dif = getAngleDifference(f_angle, last_collision_f_angle)
f_speed_dif = abs(f_speed - last_collision_f_speed)
max_x_difference = window_width
max_y_difference = window_height
max_angular_difference = 180
x_divergence = 100 * pos_x_dif /max_x_difference
y_divergence = 100 * pos_y_dif /max_y_difference
f_angular_divergence = 100 * f_angle_dif/max_angular_difference
#Apply weights.
x_divergence *= WeightData.current_weight
y_divergence *= WeightData.current_weight
f_angular_divergence *= (1 - WeightData.current_weight)
total_divergence = x_divergence + y_divergence + f_angular_divergence
divergence_data = (total_divergence, x_divergence, y_divergence, f_angular_divergence)
return divergence_data
편집 : 코드를 프로파일 링의 Here's 결과. DrawSettingsMenu()는 최악의 경우이지만 무시할 수 있습니다 (기본적으로 설정 메뉴가 표시되지 않음). 모든 "초기화 ..."기능도 무시할 수 있습니다.
내 첫 제안은 코드가 느린 곳에서 테스트하고 추측하지는 않습니다. 그래서 당신은 X 함수가 "합계"에서 Y 시간이 걸린다는 것을 알고 있습니다. – EKS
파이썬 코드에서 작동하는'pypy'를 사용해보십시오. 모든 파이썬에서 작동하지는 않지만, 응용 프로그램에서 작동하는 경우, 여러분은 황금합니다. –
이것이 CodeReview – PlasmaHH