[clblas] 66/125: A proof-of-concept python wrapper for clBLAS. Only sgemm and the init functions are callable from python.
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Fri May 29 06:57:23 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch master
in repository clblas.
commit 44234c71768c8eebe0cbe097fa182d43effa7d22
Author: Kent Knox <kent.knox at amd>
Date: Wed May 7 17:56:24 2014 -0500
A proof-of-concept python wrapper for clBLAS. Only sgemm and the init
functions are callable from python.
---
src/wrappers/python/README.txt | 61 ++++++++++++++++++++
src/wrappers/python/pyclBLAS.pxd | 84 ++++++++++++++++++++++++++++
src/wrappers/python/pyclBLAS.pyx | 117 +++++++++++++++++++++++++++++++++++++++
src/wrappers/python/setup.py | 96 ++++++++++++++++++++++++++++++++
4 files changed, 358 insertions(+)
diff --git a/src/wrappers/python/README.txt b/src/wrappers/python/README.txt
new file mode 100644
index 0000000..f77bd66
--- /dev/null
+++ b/src/wrappers/python/README.txt
@@ -0,0 +1,61 @@
+pyclBLAS setup and installation
+(I've been pronouncing it 'pickleBLAS')
+------------------------------------------------------------------------
+A python extention wrapper around clBLAS from https://github.com/clMathLibraries/clBLAS
+
+Dependencies:
+1. clBLAS from https://github.com/clMathLibraries/clBLAS ( develop branch )
+2. PyOpenCL from http://mathema.tician.de/software/pyopencl/ ( 2013.2 minimum )
+3. Cython from http://cython.org/, ( 0.18 minimum )
+4. OpenCL runtime, such as AMD's catalyst package ( AMD v2.9 SDK tested )
+
+NOTE: This has only been tested with 32-bit python on windows
+
+NOTE: Only sgemm has been wrapped as proof-of-concept
+
+Build steps:
+------------------------------------------------------------------------
+1. First, clone the clBLAS repo from github and make sure to build the
+'install' step. This is either 'make install' on linux derivatives or
+the 'install' project on Visual Studio projects. This should produce a
+'package' directory in your build tree that contains ./include, ./libXX &
+./bin.
+
+Note: it is necessary to build 32-bit clBLAS if using 32-bit python,
+and 64-bit clBLAS for 64-bit python.
+
+2. Install pyopencl. If your python distribution contains a version
+of pyopencl that is a minimum of 2013.2, then just install with the
+distributions package manager like pypm, pip, easy_install. If not, download
+pyopencl yourself and follow its directions to build and install.
+
+3. Install Cython. If your python distribution contains a version
+of cython that is a minimum of .18, then just install with the
+distributions package manager like pypm, pip, easy_install. If not,
+download cython yourself and follow its directions to build and install.
+
+4. An OpenCL SDK is required to build, which includes OpenCL header files
+and linkable libraries. One such SDK is the AMD APP SDK, which can be
+downloaded from http://developer.amd.com/tools-and-sdks/heterogeneous-computing/amd-accelerated-parallel-processing-app-sdk/
+
+5. Build the pyclBLAS extention. This is accompished by running setup.py,
+which acts as a python makefile. An example install command:
+'python setup.py --clBlasRoot=F:\code\GitHub\clMathLibraries\bin\clBLAS\develop\vs11x32\package build_ext --inplace'
+
+'python setup.py --help' prints additional command line parameters that extend
+the traditional distutils options. After successfully building the extention
+module, a pyclBLAS.pyd file appears. As shown above, it may be necessary to provide
+the setup makefile with the paths of the clBLAS 'package' directory and the
+OpenCL SDK directory. Setup.py does attempt to find the OpenCL SDK through
+the environment variable AMDAPPSDKROOT or OPENCL_ROOT.
+
+NOTE: On windows, if using a more recent version of visual studio than 2008,
+it may be necessary to trick python to using the newer version of your compiler,
+by creating an environment variable that it expects to exist as such:
+set VS90COMNTOOLS=%VS110COMNTOOLS%
+
+6. Execute demoBLAS.py file to test the pyclBLAS extention.
+
+NOTE: It may be necessary to copy the clBLAS shared library into
+the same directory as the extention module so that it can find
+clBLAS at runtime
diff --git a/src/wrappers/python/pyclBLAS.pxd b/src/wrappers/python/pyclBLAS.pxd
new file mode 100644
index 0000000..0dfbfd9
--- /dev/null
+++ b/src/wrappers/python/pyclBLAS.pxd
@@ -0,0 +1,84 @@
+################################################################################
+ # Copyright 2014 Advanced Micro Devices, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+################################################################################
+
+# This pxd file defines all the enums and structs that we plan to use from
+# python. It is used from pyclBLAS.pyx
+
+cdef extern from "clBLAS.h":
+ # These are base OpenCL enumerations that clBLAS uses
+ cdef enum:
+ CL_SUCCESS = 0
+ CL_INVALID_VALUE = -30
+ CL_INVALID_COMMAND_QUEUE = -36
+ CL_INVALID_CONTEXT = -34
+ CL_INVALID_MEM_OBJECT = -38
+ CL_INVALID_DEVICE = -33
+ CL_INVALID_EVENT_WAIT_LIST = -57
+ CL_OUT_OF_RESOURCES = -5
+ CL_OUT_OF_HOST_MEMORY = -6
+ CL_INVALID_OPERATION = -59
+ CL_COMPILER_NOT_AVAILABLE = -3
+ CL_BUILD_PROGRAM_FAILURE = -11
+
+ cdef enum clblasStatus_:
+ clblasSuccess = CL_SUCCESS
+ clblasInvalidValue = CL_INVALID_VALUE
+ clblasInvalidCommandQueue = CL_INVALID_COMMAND_QUEUE
+ clblasInvalidContext = CL_INVALID_CONTEXT
+ clblasInvalidMemObject = CL_INVALID_MEM_OBJECT
+ clblasInvalidDevice = CL_INVALID_DEVICE
+ clblasInvalidEventWaitList = CL_INVALID_EVENT_WAIT_LIST
+ clblasOutOfResources = CL_OUT_OF_RESOURCES
+ clblasOutOfHostMemory = CL_OUT_OF_HOST_MEMORY
+ clblasInvalidOperation = CL_INVALID_OPERATION
+ clblasCompilerNotAvailable = CL_COMPILER_NOT_AVAILABLE
+ clblasBuildProgramFailure = CL_BUILD_PROGRAM_FAILURE
+ clblasNotImplemented = -1024
+ clblasNotInitialized = -1023
+ clblasInvalidMatA
+ clblasInvalidMatB
+ clblasInvalidMatC
+ clblasInvalidVecX
+ clblasInvalidVecY
+ clblasInvalidDim
+ clblasInvalidLeadDimA
+ clblasInvalidLeadDimB
+ clblasInvalidLeadDimC
+ clblasInvalidIncX
+ clblasInvalidIncY
+ clblasInsufficientMemMatA
+ clblasInsufficientMemMatB
+ clblasInsufficientMemMatC
+ clblasInsufficientMemVecX
+ clblasInsufficientMemVecY
+ ctypedef clblasStatus_ clblasStatus
+
+ cdef enum clblasOrder_:
+ clblasRowMajor = 0
+ clblasColumnMajor = 1
+ ctypedef clblasStatus_ clblasOrder
+
+ cdef enum clblasTranspose_:
+ clblasNoTrans = 0
+ clblasTrans = 1
+ clblasConjTrans = 2
+ ctypedef clblasStatus_ clblasTranspose
+
+ ctypedef unsigned int cl_uint
+ ctypedef float cl_float
+ ctypedef void* cl_mem
+ ctypedef void* cl_command_queue
+ ctypedef void* cl_event
diff --git a/src/wrappers/python/pyclBLAS.pyx b/src/wrappers/python/pyclBLAS.pyx
new file mode 100644
index 0000000..2ede269
--- /dev/null
+++ b/src/wrappers/python/pyclBLAS.pyx
@@ -0,0 +1,117 @@
+################################################################################
+ # Copyright 2014 Advanced Micro Devices, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+################################################################################
+
+cimport pyclBLAS
+import pyopencl
+
+# These are prototypes from clBLAS.h that we wish to call from python
+################################################################################
+################################################################################
+cdef extern from "clBLAS.h":
+ clblasStatus clblasGetVersion( cl_uint* major, cl_uint* minor, cl_uint* patch )
+
+ clblasStatus clblasSetup( )
+
+ void clblasTeardown( )
+
+ clblasStatus clblasSgemm( clblasOrder order, clblasTranspose transA, clblasTranspose transB,
+ size_t M, size_t N, size_t K, cl_float alpha, const cl_mem A, size_t offA, size_t lda,
+ const cl_mem B, size_t offB, size_t ldb, cl_float beta, cl_mem C, size_t offC, size_t ldc,
+ cl_uint numCommandQueues, cl_command_queue* commandQueues, cl_uint numEventsInWaitList,
+ const cl_event* eventWaitList, cl_event* events)
+
+################################################################################
+################################################################################
+# enums to be accessed from python
+# TODO: is there a better way to express enums? I like how pyopencl does it,
+# they have layers of scoped constants cl.mem_flags.READ_ONLY
+# The enums below have global scope
+RowMajor = pyclBLAS.clblasRowMajor
+ColumnMajor = pyclBLAS.clblasColumnMajor
+NoTrans = pyclBLAS.clblasNoTrans
+Trans = pyclBLAS.clblasTrans
+ConjTrans = pyclBLAS.clblasConjTrans
+
+################################################################################
+################################################################################
+# The following functions are the python callable wrapper implementations
+def Setup( ):
+ result = clblasSetup( )
+ if( result != clblasSuccess ):
+ raise RuntimeError( "clblasSetup( ) failed initialization" )
+ return result
+
+################################################################################
+def Teardown( ):
+ clblasTeardown( )
+ return
+
+################################################################################
+def GetVersion( ):
+ cdef pyclBLAS.cl_uint pyMajor
+ cdef pyclBLAS.cl_uint pyMinor
+ cdef pyclBLAS.cl_uint pyPatch
+ result = clblasGetVersion( &pyMajor, &pyMinor, &pyPatch )
+ if( result != clblasSuccess ):
+ raise RuntimeError( "clblasGetVersion( ) did not return version information" )
+ return pyMajor, pyMinor, pyPatch
+
+################################################################################
+# TODO: Is there way to template these python callable functions, such that we
+# do not need to make a new function for every supported precision?
+def Sgemm( clblasOrder order, clblasTranspose transA, clblasTranspose transB,
+ size_t M, size_t N, size_t K, cl_float alpha, A, size_t offA, size_t lda,
+ B, size_t offB, size_t ldb, cl_float beta, C, size_t offC, size_t ldc,
+ cl_uint numCommandQueues, commandQueues, cl_uint numEventsInWaitList,
+ eventWaitList ):
+
+ # Simplify python wrapper to only handle 1 queue at this time
+ if( numCommandQueues != 1 ):
+ raise IndexError( "pyblasSgemm( ) requires the number of queues to be 1" )
+ cdef int pIntQueue = commandQueues.int_ptr
+ cdef cl_command_queue pcqQueue = <cl_command_queue>pIntQueue
+
+ # This logic does not yet work for numEventsInWaitList > (greater than) 1
+ # Need to figure out how python & pyopencl pass lists of objects
+ cdef int pIntWaitList = 0
+ cdef cl_event* pWaitList = NULL
+ if( numEventsInWaitList > 0 ):
+ if( numEventsInWaitList < 2 ):
+ pIntWaitList = eventWaitList.int_ptr
+ pWaitList = <cl_event*>pIntWaitList
+ else:
+ raise IndexError( "pyblasSgemm( ) requires numEventsInWaitList to be <= 1" )
+
+ # Pyopencl objects contain an int_ptr method to get access to the internally wrapped
+ # OpenCL object pointers
+ cdef cl_event outEvent = NULL
+ cdef int matA = A.int_ptr
+ cdef int matB = B.int_ptr
+ cdef int matC = C.int_ptr
+
+ # Transition execution to clBLAS
+ cdef clblasStatus result = clblasSgemm( order, transA, transB, M, N, K, alpha, <const cl_mem>matA, offA, lda,
+ <const cl_mem>matB, offB, ldb, beta, <cl_mem>matC, offC, ldc,
+ numCommandQueues, &pcqQueue, numEventsInWaitList,
+ pWaitList, &outEvent )
+
+ if( result != clblasSuccess ):
+ raise RuntimeError( "clBLAS sgemm call failed" )
+
+ # Create a pyopencl Event object from the event returned from clBLAS and return
+ # it to the user
+ sgemmEvent = pyopencl.Event.from_int_ptr( <int>outEvent )
+ return sgemmEvent
diff --git a/src/wrappers/python/setup.py b/src/wrappers/python/setup.py
new file mode 100644
index 0000000..b87aa95
--- /dev/null
+++ b/src/wrappers/python/setup.py
@@ -0,0 +1,96 @@
+################################################################################
+ # Copyright 2014 Advanced Micro Devices, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+################################################################################
+
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+from os import path, environ
+import argparse
+
+def main():
+ parser = argparse.ArgumentParser(description='Set up the pyclBLAS extension module')
+ parser.add_argument('--clRoot',
+ dest='clRoot', default=None,
+ help='Root directory to find the OpenCL SDK, which should contain the include directory')
+ parser.add_argument('--clBlasRoot',
+ dest='clBlasRoot', default=None,
+ help='Root directory to find the clBLAS SDK, which should contain the include directory')
+
+ args, unknown_args = parser.parse_known_args( )
+
+## print( "recognized args: ", args )
+## print( "unknown args: ", unknown_args )
+
+ # First check environment variables for clRoot paths
+ clRootPath = None
+ if( environ.get('OPENCL_ROOT') is not None ):
+ clRootPath = environ['OPENCL_ROOT']
+
+ # Special check for environment variable set by AMD Catalyst installer
+ if( clRootPath is None and environ.get( 'AMDAPPSDKROOT' ) is not None ):
+ clRootPath = environ['AMDAPPSDKROOT']
+
+ # If user specifies a command line options, this trumps environment variables
+ print( "args.clRoot: ", args.clRoot )
+ if( args.clRoot is not None ):
+ clRootPath = args.clRoot
+
+ if( clRootPath is None ):
+ print( "This setup.py needs to know the root path of an OpenCL installation")
+ print( "Please specify the environment variable OPENCL_ROOT with a path" )
+ print( "Or pass the command line option --clRoot" )
+ exit( )
+
+ # First check environment variables for clRoot paths
+ clBlasRootPath = None
+ if( environ.get('CLBLAS_ROOT') is not None ):
+ clBlasRootPath = environ['CLBLAS_ROOT']
+
+ # If user specifies a command line options, this trumpts environment variables
+ print( "args.clBlasRoot: ", args.clBlasRoot )
+ if( args.clBlasRoot is not None ):
+ clBlasRootPath = args.clBlasRoot
+
+ if( clBlasRootPath is None ):
+ print( "This setup.py needs to know the root path of the clBLAS installation")
+ print( "Please specify the environment variable CLBLAS_ROOT with a path" )
+ print( "or pass the command line option --clBlasRoot" )
+ exit( )
+
+ module = [
+ Extension( name = 'pyclBLAS',
+ sources = ['pyclBLAS.pyx'],
+ include_dirs = [ path.join( clRootPath, 'include' ),
+ path.join( clBlasRootPath, 'include' ) ],
+ library_dirs = [ path.join( clBlasRootPath, 'lib', 'import' ) ],
+ libraries=['clBLAS'] )
+ ]
+
+ setup(
+ name = 'pyclBLAS',
+ version = '0.0.1',
+ author = 'Kent Knox',
+ description = 'Python wrapper for clBLAS',
+ license = 'Apache License, Version 2.0',
+ cmdclass = {"build_ext": build_ext},
+ ext_modules = module,
+ script_args = unknown_args
+ )
+
+# This is the start of the execution of the python script
+# Useful for debuggers to step into script
+if __name__ == '__main__':
+ main( )
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/clblas.git
More information about the debian-science-commits
mailing list