使用ctypes传递c结构到一个函数 [英] Passing c struct to a function using ctypes

查看:542
本文介绍了使用ctypes传递c结构到一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试查询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 a cudaDeviceProp 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆