使用ctypes传递c结构到一个函数 [英] Passing c struct to a function using ctypes
问题描述
我正在尝试查询CUDA设备,而不添加pycuda依赖项。这是我到目前为止:
import ctypes
cudart = ctypes.cdll.LoadLibrary ('libcudart.so')
numDevices = ctypes.c_int()
cudart.cudaGetDeviceCount(ctypes.byref(numDevices))
print'There are',numDevices.value ,'devices'。
for x in xrange(numDevices.value):
properties = None#XXX这里是什么?
cudart.cudaGetDeviceProperties(ctypes.byref(properties),x)
打印属性
问题是,我不能创建一个空的结构传递给cudaGetDeviceProperties()。我想做这样的事情:
properties = cudart.cudaDeviceProp
pre>
但是会抛出这个错误:
AttributeError:/ usr /local/cuda/lib64/libcudart.so:undefined symbol:cudaDeviceProp
这里是相关的 CUDA文档。
(编辑)
感谢@mhawke,我得到了这个工作。对于任何想要这样做的人,我会保存你自己打字的工作:
class CudaDeviceProp ctypes.Structure):
_fields_ = [
('name',ctypes.c_char * 256),
('totalGlobalMem',ctypes.c_size_t),
('sharedMemPerBlock' ,ctypes.c_size_t),
('regsPerBlock',ctypes.c_int),
('warpSize',ctypes.c_int),
('memPitch',ctypes.c_size_t) $ b('maxThreadsPerBlock',ctypes.c_int),
('maxThreadsDim',ctypes.c_int * 3),
('maxGridSize',ctypes.c_int * 3),
('main',ctypes.c_int),
('minor',ctypes.c_int),
('mainConstMem',ctypes.c_size_t)
('textureAlignment',ctypes.c_size_t),
('texturePitchAlignment',ctypes.c_size_t),
('deviceOverlap',ctypes.c_int),
('multiProcessorCount' ,ctypes.c_int),
('canMapHostMemory',ctypes.c_int),
('kernelExecTimeoutEnabled',ctypes.c_int) $ b('computeMode',ctypes.c_int),
('maxTexture1D',ctypes.c_int),
('maxTexture1DMipmap',ctypes.c_int),
('maxTexture1DLinear',ctypes .c_int),
('maxTexture2D',ctypes.c_int * 2),
('maxTexture2DMipmap',ctypes.c_int * 2),
('maxTexture2DLinear',ctypes.c_int * 3 ),
('maxTexture2DGather',ctypes.c_int * 2),
('maxTexture3D',ctypes.c_int * 3),
('maxTexture3DAlt',ctypes.c_int * 3)
('maxTextureCubemap',ctypes.c_int),
('maxTexture1DLayered',ctypes.c_int * 2),
('maxTexture2DLayered',ctypes.c_int * 3),
('maxTextureCubemapLayered',ctypes.c_int * 2),
('maxSurface1D',ctypes.c_int),
('maxSurface2D',ctypes.c_int * 2),
('maxSurface3D' ,ctypes.c_int * 3),
('maxSurfaceCubemap',ctypes.c_int * 2),
('maxSurface2DLayered',ctypes.c_int * .c_int),
('maxSurfaceCubemapLayered',ctypes.c_int * 2),
('surfaceAlignment',ctypes.c_size_t),
('concurrentKernels',ctypes.c_int) $ b('ECCEnabled',ctypes.c_int),
('pciBusID',ctypes.c_int),
('pciDeviceID',ctypes.c_int),
('pciDomainID',ctypes .c_int),
('tccDriver',ctypes.c_int),
('asyncEngineCount',ctypes.c_int),
('unifiedAddressing',ctypes.c_int),
('memoryClockRate',ctypes.c_int),
('memoryBusWidth',ctypes.c_int),
('l2CacheSize',ctypes.c_int),
('maxThreadsPerMultiProcessor',ctypes.c_int ),
('streamPrioritiesSupported',ctypes.c_int),
('globalL1CacheSupported',ctypes.c_int),
('localL1CacheSupported',ctypes.c_int) sharedMemPerMultiprocessor',ctypes.c_size_t),
('regsPerMultiprocessor',ctypes.c_int),
('managedMemSupported',ctypes.c_int),
('isMultiGpuBoard',ctypes.c_int)
('multiGpuBoardGroupID',ctypes.c_int),
('singleToDoublePrecisionPerfRatio',ctypes.c_int),
('pageableMemoryAccess',ctypes.c_int),
('concurrentManagedAccess' ,ctypes.c_int),
]
解决方案您需要定义
ctypes.Structure
的子类,该子类指定cudaDeviceProp
结构中的所有字段。然后可以将结构的实例传递给函数。请注意,您需要以正确的顺序填写所有字段。有些是数组,所以你需要正确声明。import ctypes
class CudaDeviceProp (ctypes.Structure):
_fields_ = [('ECCEnabled',ctypes.c_int),
('asyncEngineCount',ctypes.c_int),
('canMapHostMemory',ctypes.c_int) ,
('clockRate',ctypes.c_int),
('computeMode',ctypes.c_int),
('concurrentKernels',ctypes.c_int),
('totalGlobalMem',ctypes.c_size_t),
('unifiedAddressing',ctypes.c_int),
('warpSize',ctypes.c_int)]
properties = CudaDeviceProp()
cudart.cudaGetDeviceProperties(ctypes.byref(properties),0)
I'm trying to query the CUDA devices without adding the pycuda dependency. Here's what I've got so far:
import ctypes cudart = ctypes.cdll.LoadLibrary('libcudart.so') numDevices = ctypes.c_int() cudart.cudaGetDeviceCount(ctypes.byref(numDevices)) print 'There are', numDevices.value, 'devices.' for x in xrange(numDevices.value): properties = None # XXX What goes here? cudart.cudaGetDeviceProperties(ctypes.byref(properties), x) print properties
The problem is that I can't create an empty struct to pass to cudaGetDeviceProperties(). I want to do something like this:
properties = cudart.cudaDeviceProp
But that throws this error:
AttributeError: /usr/local/cuda/lib64/libcudart.so: undefined symbol: cudaDeviceProp
Here is the relevant CUDA documentation.
(edit)
Thanks to @mhawke, I got this working. For anyone else who wants to do this, I'll save you the work of typing up the class yourself:
class CudaDeviceProp(ctypes.Structure): _fields_ = [ ('name', ctypes.c_char * 256), ('totalGlobalMem', ctypes.c_size_t), ('sharedMemPerBlock', ctypes.c_size_t), ('regsPerBlock', ctypes.c_int), ('warpSize', ctypes.c_int), ('memPitch', ctypes.c_size_t), ('maxThreadsPerBlock', ctypes.c_int), ('maxThreadsDim', ctypes.c_int * 3), ('maxGridSize', ctypes.c_int * 3), ('clockRate', ctypes.c_int), ('totalConstMem', ctypes.c_size_t), ('major', ctypes.c_int), ('minor', ctypes.c_int), ('textureAlignment', ctypes.c_size_t), ('texturePitchAlignment', ctypes.c_size_t), ('deviceOverlap', ctypes.c_int), ('multiProcessorCount', ctypes.c_int), ('kernelExecTimeoutEnabled', ctypes.c_int), ('integrated', ctypes.c_int), ('canMapHostMemory', ctypes.c_int), ('computeMode', ctypes.c_int), ('maxTexture1D', ctypes.c_int), ('maxTexture1DMipmap', ctypes.c_int), ('maxTexture1DLinear', ctypes.c_int), ('maxTexture2D', ctypes.c_int * 2), ('maxTexture2DMipmap', ctypes.c_int * 2), ('maxTexture2DLinear', ctypes.c_int * 3), ('maxTexture2DGather', ctypes.c_int * 2), ('maxTexture3D', ctypes.c_int * 3), ('maxTexture3DAlt', ctypes.c_int * 3), ('maxTextureCubemap', ctypes.c_int), ('maxTexture1DLayered', ctypes.c_int * 2), ('maxTexture2DLayered', ctypes.c_int * 3), ('maxTextureCubemapLayered', ctypes.c_int * 2), ('maxSurface1D', ctypes.c_int), ('maxSurface2D', ctypes.c_int * 2), ('maxSurface3D', ctypes.c_int * 3), ('maxSurface1DLayered', ctypes.c_int * 2), ('maxSurface2DLayered', ctypes.c_int * 3), ('maxSurfaceCubemap', ctypes.c_int), ('maxSurfaceCubemapLayered', ctypes.c_int * 2), ('surfaceAlignment', ctypes.c_size_t), ('concurrentKernels', ctypes.c_int), ('ECCEnabled', ctypes.c_int), ('pciBusID', ctypes.c_int), ('pciDeviceID', ctypes.c_int), ('pciDomainID', ctypes.c_int), ('tccDriver', ctypes.c_int), ('asyncEngineCount', ctypes.c_int), ('unifiedAddressing', ctypes.c_int), ('memoryClockRate', ctypes.c_int), ('memoryBusWidth', ctypes.c_int), ('l2CacheSize', ctypes.c_int), ('maxThreadsPerMultiProcessor', ctypes.c_int), ('streamPrioritiesSupported', ctypes.c_int), ('globalL1CacheSupported', ctypes.c_int), ('localL1CacheSupported', ctypes.c_int), ('sharedMemPerMultiprocessor', ctypes.c_size_t), ('regsPerMultiprocessor', ctypes.c_int), ('managedMemSupported', ctypes.c_int), ('isMultiGpuBoard', ctypes.c_int), ('multiGpuBoardGroupID', ctypes.c_int), ('singleToDoublePrecisionPerfRatio', ctypes.c_int), ('pageableMemoryAccess', ctypes.c_int), ('concurrentManagedAccess', ctypes.c_int), ]
解决方案You need to define a subclass of
ctypes.Structure
that specifies all of the fields in acudaDeviceProp
struct. Then you can pass an instance of the structure to the function. Note that you need to fill in all the fields in the correct order. Some of them are arrays, so you need to declare those properly.import ctypes class CudaDeviceProp(ctypes.Structure): _fields_ = [('ECCEnabled', ctypes.c_int), ('asyncEngineCount', ctypes.c_int), ('canMapHostMemory', ctypes.c_int), ('clockRate', ctypes.c_int), ('computeMode', ctypes.c_int), ('concurrentKernels', ctypes.c_int), ... ('totalGlobalMem', ctypes.c_size_t), ('unifiedAddressing', ctypes.c_int), ('warpSize', ctypes.c_int)] properties = CudaDeviceProp() cudart.cudaGetDeviceProperties(ctypes.byref(properties), 0)
这篇关于使用ctypes传递c结构到一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!