मारा मैं अजगर में एक साधारण raytracer है। एक छवि 200x200 प्रतिपादन 4 मिनट लेता है, जो मेरे स्वाद के लिए निश्चित रूप से बहुत अधिक है। मैं स्थिति में सुधार करना चाहता हूं।प्रदर्शन सुधारना समारोह
कुछ बिंदुओं: मैं प्रत्येक पिक्सेल प्रति एकाधिक किरणों गोली मार पिक्सेल प्रति 16 किरणों के कुल योग के लिए (एंटीलायज़िंग़ प्रदान करने के लिए)। 200x200x16 640000 किरणों की एक भव्य कुल है। दृश्य में कई क्षेत्र वस्तुओं पर प्रभाव के लिए प्रत्येक किरण का परीक्षण किया जाना चाहिए। रे ने भी एक नहीं बल्कि तुच्छ वस्तु
class Ray(object):
def __init__(self, origin, direction):
self.origin = numpy.array(origin)
self.direction = numpy.array(direction)
क्षेत्र से थोड़ा अधिक जटिल है, और हिट/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
, मैं कुछ रूपरेखा भाग गया, और यह है कि सबसे लंबे समय तक प्रसंस्करण प्रकट होता है समय हिट() फ़ंक्शन
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}
यह मैं आश्चर्य नहीं है में है, और मैं जितना संभव हो उतना इस मूल्य को कम करना चाहते हैं। मैं रूपरेखा लाइन गुजरती है, और परिणाम
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)
तो, ऐसा लगता है कि समय के सबसे कोड के इस हिस्से में खर्च किया जाता है है:
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
कहाँ मैं वास्तव में एक बहुत कुछ नहीं दिख रहा है अनुकूलन करने के लिए। क्या आपको कोई विचार है कि इस कोड को सी के बिना और अधिक प्रदर्शन करने के लिए कैसे बनाया जाए?
+1 बहुत अच्छी तरह से प्रस्तुत किया गया। मुझे पायथन नहीं पता है, इसलिए एक प्रश्न के रूप में: numpy.dot एक सी कार्यान्वयन के लिए बुला रहा है? यदि नहीं, तो शायद आप मैन्युअल डॉट उत्पाद गणना करके गति में सुधार कर सकते हैं। – Phrogz
हां, नमस्ते को सी में लागू किया गया है। यही कारण है कि मुझे लगता है कि सी –
में हिट फ़ंक्शन को पुन: कार्यान्वित करने के लिए बहुत कुछ नहीं है, आपकी दिशा वैक्टर यूनिट वैक्टर हैं? क्या आप उन्हें '__init__' में इकाई वैक्टर बना सकते हैं? यदि हां, तो आपका डॉट उत्पाद गणित सरल हो जाता है। – underrun