Tôi có một raytracer đơn giản trong python. dựng hình ảnh 200x200 mất 4 phút, điều đó chắc chắn là quá nhiều đối với khẩu vị của tôi. Tôi muốn cải thiện tình hình.Cải thiện hiệu suất của chức năng đánh bóng raytracing
Một số điểm: Tôi chụp nhiều tia cho mỗi pixel (để cung cấp tính năng chống răng cưa) với tổng cộng 16 tia mỗi pixel. 200x200x16 là tổng cộng 640000 tia. Mỗi tia phải được kiểm tra tác động lên nhiều đối tượng Sphere trong cảnh. Ray cũng là một đối tượng chứ không phải tầm thường
class Ray(object):
def __init__(self, origin, direction):
self.origin = numpy.array(origin)
self.direction = numpy.array(direction)
Sphere là hơi phức tạp hơn, và mang logic cho hit/nohit:
class Sphere(object):
def __init__(self, center, radius, color):
self.center = numpy.array(center)
self.radius = numpy.array(radius)
self.color = color
@profile
def hit(self, ray):
temp = ray.origin - self.center
a = numpy.dot(ray.direction, ray.direction)
b = 2.0 * numpy.dot(temp, ray.direction)
c = numpy.dot(temp, temp) - self.radius * self.radius
disc = b * b - 4.0 * a * c
if (disc < 0.0):
return None
else:
e = math.sqrt(disc)
denom = 2.0 * a
t = (-b - e)/denom
if (t > 1.0e-7):
normal = (temp + t * ray.direction)/self.radius
hit_point = ray.origin + t * ray.direction
return ShadeRecord.ShadeRecord(normal=normal,
hit_point=hit_point,
parameter=t,
color=self.color)
t = (-b + e)/denom
if (t > 1.0e-7):
normal = (temp + t * ray.direction)/self.radius hit_point = ray.origin + t * ray.direction
return ShadeRecord.ShadeRecord(normal=normal,
hit_point=hit_point,
parameter=t,
color=self.color)
return None
Bây giờ, tôi chạy một số hồ sơ, và nó xuất hiện rằng việc xử lý dài nhất thời gian nằm trong hàm hit()
ncalls tottime percall cumtime percall filename:lineno(function)
2560000 118.831 0.000 152.701 0.000 raytrace/objects/Sphere.py:12(hit)
1960020 42.989 0.000 42.989 0.000 {numpy.core.multiarray.array}
1 34.566 34.566 285.829 285.829 raytrace/World.py:25(render)
7680000 33.796 0.000 33.796 0.000 {numpy.core._dotblas.dot}
2560000 11.124 0.000 163.825 0.000 raytrace/World.py:63(f)
640000 10.132 0.000 189.411 0.000 raytrace/World.py:62(hit_bare_bones_object)
640023 6.556 0.000 170.388 0.000 {map}
Điều này không làm tôi ngạc nhiên và tôi muốn giảm giá trị này càng nhiều càng tốt. Tôi vượt qua để lót hồ sơ, và kết quả là
Line # Hits Time Per Hit % Time Line Contents
==============================================================
12 @profile
13 def hit(self, ray):
14 2560000 27956358 10.9 19.2 temp = ray.origin - self.center
15 2560000 17944912 7.0 12.3 a = numpy.dot(ray.direction, ray.direction)
16 2560000 24132737 9.4 16.5 b = 2.0 * numpy.dot(temp, ray.direction)
17 2560000 37113811 14.5 25.4 c = numpy.dot(temp, temp) - self.radius * self.radius
18 2560000 20808930 8.1 14.3 disc = b * b - 4.0 * a * c
19
20 2560000 10963318 4.3 7.5 if (disc < 0.0):
21 2539908 5403624 2.1 3.7 return None
22 else:
23 20092 75076 3.7 0.1 e = math.sqrt(disc)
24 20092 104950 5.2 0.1 denom = 2.0 * a
25 20092 115956 5.8 0.1 t = (-b - e)/denom
26 20092 83382 4.2 0.1 if (t > 1.0e-7):
27 20092 525272 26.1 0.4 normal = (temp + t * ray.direction)/self.radius
28 20092 333879 16.6 0.2 hit_point = ray.origin + t * ray.direction
29 20092 299494 14.9 0.2 return ShadeRecord.ShadeRecord(normal=normal, hit_point=hit_point, parameter=t, color=self.color)
Vì vậy, dường như phần lớn thời gian là chi tiêu trong đoạn mã này:
temp = ray.origin - self.center
a = numpy.dot(ray.direction, ray.direction)
b = 2.0 * numpy.dot(temp, ray.direction)
c = numpy.dot(temp, temp) - self.radius * self.radius
disc = b * b - 4.0 * a * c
ở đâu tôi không thực sự nhìn thấy rất nhiều để tối ưu hóa. Bạn có bất kỳ ý tưởng làm thế nào để làm cho mã này hiệu quả hơn mà không đi C?
+1 Rất được trình bày. Tôi không biết Python, do đó, như một câu hỏi: là numpy.dot gọi xuống để thực hiện một C? Nếu không, có lẽ bạn có thể cải thiện tốc độ bằng cách thực hiện tính toán sản phẩm chấm thủ công. – Phrogz
Có, được thực hiện một cách gọn gàng trong C. Đó là lý do tại sao tôi có cảm giác không có nhiều để đạt được để thực hiện lại hàm hit trong C. –
là các vectơ đơn vị vectơ hướng của bạn? bạn có thể biến chúng thành các vector đơn vị trong '__init__' không? nếu vậy, phép toán sản phẩm chấm của bạn trở nên đơn giản hơn. – underrun