gpt4 book ai didi

python - 提高光线追踪命中函数的性能

转载 作者:太空狗 更新时间:2023-10-29 17:28:59 24 4
gpt4 key购买 nike

我在 python 中有一个简单的光线追踪器。渲染一张 200x200 的图像需要 4 分钟,这对我来说太过分了。我想改善这种情况。

一些要点:我为每个像素发射多条光线(以提供抗锯齿),每个像素总共有 16 条光线。 200x200x16 总共有 640000 条光线。必须测试每条光线对场景中多个球体对象的影响。 Ray也是一个相当琐碎的对象

class Ray(object):
def __init__(self, origin, direction):
self.origin = numpy.array(origin)
self.direction = numpy.array(direction)

Sphere 稍微复杂一些,包含命中/未命中的逻辑:

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

现在,我进行了一些分析,似乎最长的处理时间在 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}

这并不让我吃惊,我想尽可能地降低这个值。我传递给线路分析,结果是

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

我真的没有看到太多需要优化的地方。您是否知道如何在不使用 C 的情况下使此代码更高效?

最佳答案

查看您的代码,您的主要问题似乎是您的代码行被调用了 2560000 次。无论您在该代码中做什么类型的工作,这往往会花费大量时间。但是,使用 numpy ,您可以将大量这项工作聚合到少量的 numpy 调用中。

首先要做的是将光线组合成大型阵列。不要使用具有 1x3 向量作为原点和方向的射线对象,而是使用具有命中检测所需的所有射线的 Nx3 数组。你的命中函数的顶部最终看起来像这样:

temp = rays.origin - self.center
b = 2.0 * numpy.sum(temp * rays.direction,1)
c = numpy.sum(numpy.square(temp), 1) - self.radius * self.radius
disc = b * b - 4.0 * c

下一部分你可以使用

possible_hits = numpy.where(disc >= 0.0)
a = a[possible_hits]
disc = disc[possible_hits]
...

仅使用通过判别测试的值继续。通过这种方式,您可以轻松获得数量级的性能提升。

关于python - 提高光线追踪命中函数的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6528214/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com