rindow/rindow-opencl-ffi

1.0.2 2024-04-25 15:17 UTC

This package is auto-updated.

Last update: 2024-08-25 15:56:07 UTC


README

状态: Build Status Downloads Latest Stable Version License

您可以在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";