gpt4 book ai didi

python - 为 pyopengl 和 numpy 构建交错缓冲区

转载 作者:太空狗 更新时间:2023-10-29 21:57:35 24 4
gpt4 key购买 nike

在将交错数组发送到 pyOpengl 的 glInterleavedArrays/glDrawArrays 之前,我正在尝试对交错数组中的一堆顶点和纹理坐标进行批处理。唯一的问题是我无法找到一种足够快的方法来将数据附加到 numpy 数组中。

有更好的方法吗?我原以为预先分配数组然后用数据填充它会更快,但是生成 python 列表并将其转换为 numpy 数组会“更快”。尽管 4096 个四边形的 15 毫秒似乎很慢。

我已经包含了一些示例代码及其时间。

#!/usr/bin/python

import timeit
import numpy
import ctypes
import random

USE_RANDOM=True
USE_STATIC_BUFFER=True

STATIC_BUFFER = numpy.empty(4096*20, dtype=numpy.float32)

def render(i):
# pretend these are different each time
if USE_RANDOM:
tex_left, tex_right, tex_top, tex_bottom = random.random(), random.random(), random.random(), random.random()
left, right, top, bottom = random.random(), random.random(), random.random(), random.random()
else:
tex_left, tex_right, tex_top, tex_bottom = 0.0, 1.0, 1.0, 0.0
left, right, top, bottom = -1.0, 1.0, 1.0, -1.0

ibuffer = (
tex_left, tex_bottom, left, bottom, 0.0, # Lower left corner
tex_right, tex_bottom, right, bottom, 0.0, # Lower right corner
tex_right, tex_top, right, top, 0.0, # Upper right corner
tex_left, tex_top, left, top, 0.0, # upper left
)

return ibuffer



# create python list.. convert to numpy array at end
def create_array_1():
ibuffer = []
for x in xrange(4096):
data = render(x)
ibuffer += data

ibuffer = numpy.array(ibuffer, dtype=numpy.float32)
return ibuffer

# numpy.array, placing individually by index
def create_array_2():
if USE_STATIC_BUFFER:
ibuffer = STATIC_BUFFER
else:
ibuffer = numpy.empty(4096*20, dtype=numpy.float32)
index = 0
for x in xrange(4096):
data = render(x)
for v in data:
ibuffer[index] = v
index += 1
return ibuffer

# using slicing
def create_array_3():
if USE_STATIC_BUFFER:
ibuffer = STATIC_BUFFER
else:
ibuffer = numpy.empty(4096*20, dtype=numpy.float32)
index = 0
for x in xrange(4096):
data = render(x)
ibuffer[index:index+20] = data
index += 20
return ibuffer

# using numpy.concat on a list of ibuffers
def create_array_4():
ibuffer_concat = []
for x in xrange(4096):
data = render(x)
# converting makes a diff!
data = numpy.array(data, dtype=numpy.float32)
ibuffer_concat.append(data)
return numpy.concatenate(ibuffer_concat)

# using numpy array.put
def create_array_5():
if USE_STATIC_BUFFER:
ibuffer = STATIC_BUFFER
else:
ibuffer = numpy.empty(4096*20, dtype=numpy.float32)
index = 0
for x in xrange(4096):
data = render(x)
ibuffer.put( xrange(index, index+20), data)
index += 20
return ibuffer

# using ctype array
CTYPES_ARRAY = ctypes.c_float*(4096*20)
def create_array_6():
ibuffer = []
for x in xrange(4096):
data = render(x)
ibuffer += data
ibuffer = CTYPES_ARRAY(*ibuffer)
return ibuffer

def equals(a, b):

for i,v in enumerate(a):
if b[i] != v:
return False
return True



if __name__ == "__main__":
number = 100

# if random, don't try and compare arrays
if not USE_RANDOM and not USE_STATIC_BUFFER:
a = create_array_1()
assert equals( a, create_array_2() )
assert equals( a, create_array_3() )
assert equals( a, create_array_4() )
assert equals( a, create_array_5() )
assert equals( a, create_array_6() )

t = timeit.Timer( "testing2.create_array_1()", "import testing2" )
print 'from list:', t.timeit(number)/number*1000.0, 'ms'

t = timeit.Timer( "testing2.create_array_2()", "import testing2" )
print 'array: indexed:', t.timeit(number)/number*1000.0, 'ms'

t = timeit.Timer( "testing2.create_array_3()", "import testing2" )
print 'array: slicing:', t.timeit(number)/number*1000.0, 'ms'

t = timeit.Timer( "testing2.create_array_4()", "import testing2" )
print 'array: concat:', t.timeit(number)/number*1000.0, 'ms'

t = timeit.Timer( "testing2.create_array_5()", "import testing2" )
print 'array: put:', t.timeit(number)/number*1000.0, 'ms'

t = timeit.Timer( "testing2.create_array_6()", "import testing2" )
print 'ctypes float array:', t.timeit(number)/number*1000.0, 'ms'

使用随机数计时:

$ python testing2.py
from list: 15.0486779213 ms
array: indexed: 24.8184704781 ms
array: slicing: 50.2214789391 ms
array: concat: 44.1691994667 ms
array: put: 73.5879898071 ms
ctypes float array: 20.6674289703 ms

编辑说明:更改代码为每次渲染生成随机数,以减少对象重用并每次模拟不同的顶点。

编辑注释 2:添加静态缓冲区并强制所有 numpy.empty() 使用 dtype=float32

注意 1/Apr/2010:仍然没有进展,我真的不觉得任何答案已经解决了问题。

最佳答案

create_array_1 如此快的原因似乎是(python)列表中的项目都指向同一个对象。如果你测试你可以看到这个:

print (ibuffer[0] is ibuffer[1])

在子程序中。在 create_array_1 中这是真的(在创建 numpy 数组之前),而在 create_array_2 中这总是假的。我猜这意味着数组转换中的数据转换步骤只需要在 create_array_1 中发生一次,而在 create_array_2 中发生 4096 次。

如果是这个原因,我想如果你让 render 生成随机数据,时间会有所不同。 Create_array_5 最慢,因为它会在您每次向末尾添加数据时创建一个新数组。

关于python - 为 pyopengl 和 numpy 构建交错缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2350110/

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