安装 Yosemite 后,我必须升级 numpy、PyOpenGL 等。
现在,以前运行的程序给了我以下堆栈跟踪:
file "latebind.pyx", line 44, in OpenGL_accelerate.latebind.Curry.__call__ (src/latebind.c:1201)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/OpenGL/GL/VERSION/GL_1_5.py", line 89, in glBufferData
return baseOperation( target, size, data, usage )
File "latebind.pyx", line 32, in OpenGL_accelerate.latebind.LateBind.__call__ (src/latebind.c:989)
File "wrapper.pyx", line 314, in OpenGL_accelerate.wrapper.Wrapper.__call__ (src/wrapper.c:6505)
File "wrapper.pyx", line 311, in OpenGL_accelerate.wrapper.Wrapper.__call__ (src/wrapper.c:6439)
ctypes.ArgumentError: ("argument 3: <class 'OpenGL.error.CopyError'>: from_param received a non-contiguous array! []", (GL_ARRAY_BUFFER, 0, array([],
dtype=[('time', '<f8'), ('data', [('cluster_index', '<i4'), ('delta_diag_out', '<f8')])]), GL_STREAM_DRAW))
看起来 PyOpenGL 希望我的数组是连续的。查看 PyOpenGL 中 numpy_formathandler.pyx 的源代码:
if not PyArray_ISCARRAY( instance ):
raise CopyError(
"""from_param received a non-contiguous array! %s"""%(
working,
)
)
PyArray_ISCARRAY(arr) “如果 arr 的数据区域是 C 风格连续的,则评估为 true,并且 PyArray_ISBEHAVED (arr) 为 true。”其中“PyArray_ISBEHAVED(arr)
如果 arr 的数据区域已对齐且可写,并且根据其描述符处于机器字节顺序,则评估为 true。”
但是,那flags
推送到 OpenGL 的数组的属性是:
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : False
UPDATEIFCOPY : False
也许我需要对齐数组?但使用numpy.require
with requirements={'ALIGNED': True}
似乎不起作用。
我查看了 numpy 1.9 中的变化,其中表明:
有一个新的编译时环境变量
NPY_RELAXED_STRIDES_CHECKING。如果该变量设置为 1,则 numpy
会考虑更多的数组是 C 或 F 连续的——例如,它
可能有一个列向量,它被认为是 C-
和F-同时连续。新的定义更加准确
允许更快的代码,减少不必要的副本,并且
内部简化了 numpy 的代码。不过也有可能会断掉
第三方库对
C 和 F 连续数组的步长值。 (目前也是
已知这会破坏使用内存视图的 Cython 代码,这将是
在 Cython 中已修复。)这将成为未来版本中的默认设置,因此
请立即针对 NUMPY 构建的代码测试您的代码:
NPY_RELAXED_STRIDES_CHECKING=1 python setup.py 安装
你可以检查
通过运行以下命令来判断 NPY_RELAXED_STRIDES_CHECKING 是否有效:
np.ones((10, 1), order="C").flags.f_contigulous
这将是真的,如果
启用宽松步幅检查,否则启用 False。典型的
到目前为止我们看到的问题是与 C 连续的 C 代码一起工作
数组,并假设可以通过查看来访问 itemsize
PyArray_STRIDES(arr) 数组中的最后一个元素。放松时
跨步是有效的,这不是真的(事实上,它从来都不是)
在某些极端情况下是正确的)。相反,请使用 PyArray_ITEMSIZE(arr)。
然而,np.ones((10, 1), order="C").flags.f_contiguous
在我的系统上是 False。所以我很困惑。是什么改变导致 opengl 认为我发送给它的数组不连续且不对齐?有没有办法强制对齐数组?