rindow / rindow-opencl-ffi
PHP上FFI的OpenCL库
1.0.2
2024-04-25 15:17 UTC
Requires
- php: ^8.1
- interop-phpobjects/polite-math: ~1.0.7
Requires (Dev)
- ext-ffi: *
- rindow/rindow-math-buffer-ffi: ~1.0.0
README
您可以在PHP上使用OpenCL。OpenCL的版本限制为1.2(1.1受限制),我们正在考虑将其移植到更广泛的环境中。
由于我们的目标是与Rindow神经网络库一起使用,目前我们只提供了所需的最小功能。未来将进行扩展。
请参阅关于缓冲区对象的文档,见Rindow Mathematics网页。
要求
- PHP 8.1或PHP8.2或PHP8.3
- interop-phpobjects/polite-math 1.0.5或更高版本
- Interop php objects for Math中的FFI-Buffer。(例如,rindow/rindow-math-buffer-ffi)
- OpenCL 1.2 ICL加载器和OpenCL 1.1/1.2驱动程序
- Windows / Linux
Windows的AMD GPU/APU和Intel集成GPU驱动程序包括OpenCL驱动程序。如果您想在Linux上使用它,您需要明确安装OpenCL驱动程序。
如何设置
设置OpenCL
在Windows上,您可以使用OpenCL而不做任何事情。
在Linux上,安装ICL加载器和适合您硬件的驱动程序。
例如,在Linux标准AMD驱动程序的情况下,安装如下
$ sudo apt install clinfo $ sudo apt install mesa-opencl-icd
Linux标准OpenCL驱动程序包括
- mesa-opencl-icd
- beignet-opencl-icd
- intel-opencl-icd
- nvidia-opencl-icd-xxx
- pocl-opencl-icd
设置Rindow OpenCL-FFI
使用composer安装。
$ composer require rindow/rindow-opencl-ffi
如何使用
让我们运行示例程序。
显示OpenCL信息的示例
<?php include __DIR__.'/vendor/autoload.php'; use Interop\Polite\Math\Matrix\OpenCL; use Rindow\OpenCL\FFI\OpenCLFactory; $ocl = new OpenCLFactory(); $platforms = $ocl->PlatformList(); $m = $platforms->count(); for($p=0;$p<$m;$p++) { echo "platform(".$p.")\n"; echo " CL_PLATFORM_NAME=".$platforms->getInfo($p,OpenCL::CL_PLATFORM_NAME)."\n"; echo " CL_PLATFORM_PROFILE=".$platforms->getInfo($p,OpenCL::CL_PLATFORM_PROFILE)."\n"; echo " CL_PLATFORM_VERSION=".$platforms->getInfo($p,OpenCL::CL_PLATFORM_VERSION)."\n"; echo " CL_PLATFORM_VENDOR=".$platforms->getInfo($p,OpenCL::CL_PLATFORM_VENDOR)."\n"; $devices = $ocl->DeviceList($platforms,index:$p); $n = $devices->count(); for($i=0;$i<$n;$i++) { echo " device(".$i.")\n"; echo " CL_DEVICE_VENDOR_ID=".$devices->getInfo($i,OpenCL::CL_DEVICE_VENDOR_ID)."\n"; echo " CL_DEVICE_NAME=".$devices->getInfo($i,OpenCL::CL_DEVICE_NAME)."\n"; echo " CL_DEVICE_TYPE=("; $device_type = $devices->getInfo($i,OpenCL::CL_DEVICE_TYPE); if($device_type&OpenCL::CL_DEVICE_TYPE_CPU) { echo "CPU,"; } if($device_type&OpenCL::CL_DEVICE_TYPE_GPU) { echo "GPU,"; } if($device_type&OpenCL::CL_DEVICE_TYPE_ACCELERATOR) { echo "ACCEL,"; } if($device_type&OpenCL::CL_DEVICE_TYPE_CUSTOM) { echo "CUSTOM,"; } echo ")\n"; echo " CL_DEVICE_VENDOR=".$devices->getInfo($i,OpenCL::CL_DEVICE_VENDOR)."\n"; echo " CL_DEVICE_PROFILE=".$devices->getInfo($i,OpenCL::CL_DEVICE_PROFILE)."\n"; echo " CL_DEVICE_VERSION=".$devices->getInfo($i,OpenCL::CL_DEVICE_VERSION)."\n"; echo " CL_DEVICE_OPENCL_C_VERSION=".$devices->getInfo($i,OpenCL::CL_DEVICE_OPENCL_C_VERSION)."\n"; } }
编译和运行OpenCL程序的示例
$ composer require rindow/rindow-opencl-ffi $ composer require rindow/rindow-math-buffer-ffi
<?php include __DIR__.'/vendor/autoload.php'; use Interop\Polite\Math\Matrix\OpenCL; use Interop\Polite\Math\Matrix\NDArray; use Rindow\OpenCL\FFI\OpenCLFactory; use Rindow\Math\Buffer\FFI\BufferFactory; $ocl = new OpenCLFactory(); $hostBufferFactory = new BufferFactory(); $NWITEMS = 64; $context = $ocl->Context(OpenCL::CL_DEVICE_TYPE_DEFAULT); $queue = $ocl->CommandQueue($context); $sources = [ "__kernel void saxpy(const global float * x,\n". " __global float * y,\n". " const float a)\n". "{\n". " uint gid = get_global_id(0);\n". " y[gid] = a* x[gid] + y[gid];\n". "}\n" ]; $program = $ocl->Program($context,$sources); try { $program->build(); } catch(\RuntimeException $e) { echo $e->getMessage()."\n"; switch($e->getCode()) { case OpenCL::CL_BUILD_PROGRAM_FAILURE: { echo "CL_PROGRAM_BUILD_STATUS=".$program->getBuildInfo(OpenCL::CL_PROGRAM_BUILD_STATUS)."\n"; echo "CL_PROGRAM_BUILD_OPTIONS=".safestring($program->getBuildInfo(OpenCL::CL_PROGRAM_BUILD_OPTIONS))."\n"; echo "CL_PROGRAM_BUILD_LOG=".safestring($program->getBuildInfo(OpenCL::CL_PROGRAM_BUILD_LOG))."\n"; echo "CL_PROGRAM_BINARY_TYPE=".safestring($program->getBuildInfo(OpenCL::CL_PROGRAM_BINARY_TYPE))."\n"; } case OpenCL::CL_COMPILE_PROGRAM_FAILURE: { echo "CL_PROGRAM_BUILD_LOG=".safestring($program->getBuildInfo(OpenCL::CL_PROGRAM_BUILD_LOG))."\n"; } } throw $e; } $kernel = $ocl->Kernel($program,"saxpy"); $hostX = $hostBufferFactory->Buffer( $NWITEMS,NDArray::float32 ); $hostY = $hostBufferFactory->Buffer( $NWITEMS,NDArray::float32 ); for($i=0;$i<$NWITEMS;$i++) { $hostX[$i] = $i; $hostY[$i] = $NWITEMS-1-$i; } $a = 2.0; $bufX = $ocl->Buffer($context,intval($NWITEMS*32/8), OpenCL::CL_MEM_READ_ONLY|OpenCL::CL_MEM_COPY_HOST_PTR, $hostX); $bufY = $ocl->Buffer($context,intval($NWITEMS*32/8), OpenCL::CL_MEM_READ_WRITE|OpenCL::CL_MEM_COPY_HOST_PTR, $hostY); $kernel->setArg(0,$bufX); $kernel->setArg(1,$bufY); $kernel->setArg(2,$a,NDArray::float32); // enqueueNDRange $global_work_size = [$NWITEMS]; $local_work_size = [1]; $kernel->enqueueNDRange($queue,$global_work_size,$local_work_size); // complete kernel $queue->finish(); $bufY->read($queue,$hostY); for($i=0;$i<$NWITEMS;$i++) { echo $hostY[$i].","; } echo "\n";