diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b638f09..b6a9516 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,32 +1,71 @@ name: tests -on: [push] +on: + push: + branches: + - main jobs: - no_ext_tests: + tests: runs-on: ubuntu-22.04 strategy: fail-fast: true matrix: php: ['8.1','8.2','8.3'] + ffi: ['','ffi'] steps: + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + # PHP Extras + coverage: none + tools: composer, phpunit:10.5 + #ini-values: "memory_limit=512M" + extensions: ${{ matrix.ffi }} + + - name: Install Libs + run: | + if [ 'ffi' == '${{ matrix.ffi }}' ] ; then + sudo apt install -y libopenblas-base liblapacke + wget https://github.com/rindow/rindow-matlib/releases/download/1.0.0/rindow-matlib_1.0.0_amd64.deb + sudo apt install -y ./rindow-matlib_1.0.0_amd64.deb + sudo update-alternatives --set librindowmatlib.so /usr/lib/rindowmatlib-serial/librindowmatlib.so + fi + - name: Checkout codes uses: "actions/checkout@v4" + - name: Checkout math-matrix tests + run: | + ( cd .. && git clone https://github.com/rindow/rindow-math-matrix ) + ( cd ../rindow-math-matrix && git checkout 2.0.3 ) + + #- name: Composer + # uses: php-actions/composer@v6 + # with: + # php_version: ${{ matrix.php }} + # php_extensions: ffi + - name: Composer - uses: php-actions/composer@v6 - with: - php_version: ${{ matrix.php }} - php_extensions: ffi + run: composer update - - name: PHPUnit Tests - uses: php-actions/phpunit@v3 + - name: PHP Static Analysys + uses: php-actions/phpstan@v3 with: - configuration: tests/phpunit.xml - version: 10.5 php_version: ${{ matrix.php }} - php_extensions: ffi - filter: ReleaseTest + path: src/ + + #- name: PHPUnit Tests + # uses: php-actions/phpunit@v3 + # with: + # configuration: tests/phpunit.xml + # version: 10.5 + # php_version: ${{ matrix.php }} + # php_extensions: ffi + # filter: ReleaseTest + - name: PHPUnit Tests with ${{ matrix.ffi }}. + run: phpunit -c tests diff --git a/README.md b/README.md index 1a48773..f92db3d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ Rindow Math Matrix's Drivers for Matlib with PHP FFI ==================================================== + Status: [![Build Status](https://github.com/rindow/rindow-math-matrix-matlibffi/workflows/tests/badge.svg)](https://github.com/rindow/rindow-math-matrix-matlibffi/actions) [![Downloads](https://img.shields.io/packagist/dt/rindow/rindow-math-matrix-matlibffi)](https://packagist.org/packages/rindow/rindow-math-matrix-matlibffi) @@ -28,7 +29,7 @@ Requirements - OpenBLAS 0.3.20 or later - OpenCL 1.1 or later - CLBlast 1.5.2 or later -- Windows 10/11 or Ubuntu 20.04 LTS or later +- Windows 10/11 or Linux(Ubuntu 20.04 or Debian 12 or later) ### Download pre-build binaries from each projects @@ -40,7 +41,8 @@ Download the pre-build binary files from each project's release page. - [OpenBLAS](https://github.com/xianyi/OpenBLAS/releases) - [CLBlast](https://github.com/CNugteren/CLBlast/releases) -### Setup for Windows +Setup for Windows +================= Download the binary file, unzip it, and copy it to the execution directory. @@ -63,12 +65,21 @@ C:\TMP> PATH %PATH%;\path\to\binary\directories\bin C:\TMP> cd \your\progject\directory C:\PRJ> composer require rindow/rindow-math-matrix C:\PRJ> composer require rindow/rindow-math-matrix-matlibffi +C:\PRJ> vendor/bin/rindow-math-matrix +Service Level : Accelerated +Buffer Factory : Rindow\Math\Buffer\FFI\BufferFactory +BLAS Driver : Rindow\OpenBLAS\FFI\Blas(THREAD) +LAPACK Driver : Rindow\OpenBLAS\FFI\Lapack +Math Driver : Rindow\Matlib\FFI\Matlib(OPENMP) +OpenCL Factory : Rindow\OpenCL\FFI\OpenCLFactory +CLBlast Factory : Rindow\CLBlast\FFI\CLBlastFactory ``` The OpenCL 1.2 environment is already set up if you are using the Windows standard driver. -### Setup for Ubuntu +Setup for Linux +=============== Install each library using the apt command. @@ -78,24 +89,22 @@ $ php -m | grep FFI FFI ``` -Install the fast matrix calculation library. -And then set the rindow-matlib to serial mode for use with PHP. +Download the pre-build binary file. + +- https://github.com/rindow/rindow-matlib/releases + +Please install using the apt command. ```shell -$ mkdir -p /your/project/directory -$ cd /your/project/directory -$ sudo apt install libopenblas-base liblapacke -$ wget https://github.com/rindow/rindow-matlib/releases/download/X.X.X/rindow-matlib_X.X.X_amd64.deb $ sudo apt install ./rindow-matlib_X.X.X_amd64.deb -$ sudo update-alternatives --config librindowmatlib.so -There are 2 choices for the alternative librindowmatlib.so (providing /usr/lib/librindowmatlib.so). +``` - Selection Path Priority Status ------------------------------------------------------------- -* 0 /usr/lib/rindowmatlib-openmp/librindowmatlib.so 95 auto mode - 1 /usr/lib/rindowmatlib-openmp/librindowmatlib.so 95 manual mode - 2 /usr/lib/rindowmatlib-serial/librindowmatlib.so 90 manual mode +Since rindow-matlib currently uses OpenMP, choose the OpenMP version for OpenBLAS as well. -Press to keep the current choice[*], or type selection number: 2 +Using the pthread version of OpenBLAS can cause conflicts and become unstable and slow. +This issue does not occur on Windows. + +```shell +$ sudo apt install libopenblas0-openmp ``` If you want to use GPU, install the OpenCL environment. @@ -115,22 +124,36 @@ $ sudo ln -s /usr/lib/clc /usr/local/usr/lib/clc ``` And then, Install the fast matrix calculation library for OpenCL. -Please download the CLBlast installation script from the rindow-clblast-ffi release page. +If you use Ubuntu22.04 or Debian 12 or later, You can install it from distribution packages. +```shell +$ sudo apt install libclblast1 +``` +If You use Ubuntu20.04 or Debian 11, You need to download clblast from Github and make deb file. +Please download the CLBlast installation script from the rindow-clblast-ffi release page. ```shell $ wget https://github.com/rindow/rindow-clblast-ffi/releases/download/X.X.X/clblast-packdeb.zip $ unzip clblast-packdeb.zip $ sh clblast-packdeb.sh -$ sudo apt install ./clblast_X.X.X-1+ubuntuXX.XX_amd64.deb +$ sudo apt install ./clblast_X.X.X_amd64.deb ``` -Install the rindow-math-matrix on your project directory. +And then, Install the rindow-math-matrix on your project directory. ```shell $ composer require rindow/rindow-math-matrix $ composer require rindow/rindow-math-matrix-matlibffi +$ vendor/bin/rindow-math-matrix +Service Level : Accelerated +Buffer Factory : Rindow\Math\Buffer\FFI\BufferFactory +BLAS Driver : Rindow\OpenBLAS\FFI\Blas(OPENMP) +LAPACK Driver : Rindow\OpenBLAS\FFI\Lapack +Math Driver : Rindow\Matlib\FFI\Matlib(OPENMP) +OpenCL Factory : Rindow\OpenCL\FFI\OpenCLFactory +CLBlast Factory : Rindow\CLBlast\FFI\CLBlastFactory ``` ### Check driver status + You can check the driver settings by running the sample below. ```php service()->info(); ```shell $ php status.php -Service Level: Accelerated -Buffer Factory: Rindow\Math\Buffer\FFI\BufferFactory -BLAS Driver: Rindow\OpenBLAS\FFI\Blas -LAPACK Driver: Rindow\OpenBLAS\FFI\Lapack -Math Driver: Rindow\Matlib\FFI\Matlib +Service Level : Accelerated +Buffer Factory : Rindow\Math\Buffer\FFI\BufferFactory +BLAS Driver : Rindow\OpenBLAS\FFI\Blas(OPENMP) +LAPACK Driver : Rindow\OpenBLAS\FFI\Lapack +Math Driver : Rindow\Matlib\FFI\Matlib(OPENMP) +OpenCL Factory : Rindow\OpenCL\FFI\OpenCLFactory +CLBlast Factory : Rindow\CLBlast\FFI\CLBlastFactory +``` + +### Troubleshooting for Linux + +Since rindow-matlib currently uses OpenMP, choose the OpenMP version for OpenBLAS as well. + +Using the pthread version of OpenBLAS can cause conflicts and become unstable and slow. +This issue does not occur on Windows. + +If you have already installed the pthread version of OpenBLAS, +```shell +$ sudo apt remove libopenblas0-pthread +``` + +But if you can't remove it, you can switch to it using the update-alternatives command. + +```shell +$ sudo update-alternatives --config libopenblas.so.0-x86_64-linux-gnu +$ sudo update-alternatives --config liblapack.so.3-x86_64-linux-gnu ``` -### Acceleration with GPU +If you really want to use the pthread version of OpenBLAS, please switch to the serial version of rindow-matlib. + +There are no operational mode conflicts with OpenBLAS on Windows. + +But, If you really want to use the pthread version of OpenBLAS, please switch to the serial version of rindow-matlib. + +```shell +$ sudo update-alternatives --config librindowmatlib.so +There are 2 choices for the alternative librindowmatlib.so (providing /usr/lib/librindowmatlib.so). + + Selection Path Priority Status +------------------------------------------------------------ +* 0 /usr/lib/rindowmatlib-openmp/librindowmatlib.so 95 auto mode + 1 /usr/lib/rindowmatlib-openmp/librindowmatlib.so 95 manual mode + 2 /usr/lib/rindowmatlib-serial/librindowmatlib.so 90 manual mode + +Press to keep the current choice[*], or type selection number: 2 +``` +Choose the "rindowmatlib-serial". + + +Acceleration with GPU +===================== You can use GPU acceleration on OpenCL. @@ -169,6 +235,6 @@ If you have testable hardware, please test using the proprietary driver. On the other hand, I tested with Ivy-bridge of Intel CPU and Integrated GPU. -Windows 10 standard OpenCL driver worked fine, but it was very slow and occasionally crashed. +It now works comfortably with various adjustments on Windows 10 Standard OpenCL Driver. However, the old Intel Integrated GPU is not very high compared to its CPU performance, so please use the right person in the right place. And it worked fine and fast in Ubuntu 20.04 + beignet-opencl-icd environment. diff --git a/composer.json b/composer.json index 9ef7779..832cd62 100644 --- a/composer.json +++ b/composer.json @@ -7,13 +7,13 @@ "require": { "php": "^8.1", "ext-ffi": "*", - "interop-phpobjects/polite-math": "~1.0.6", - "rindow/rindow-math-matrix": "~2.0.0", - "rindow/rindow-math-buffer-ffi": "~1.0.0", - "rindow/rindow-openblas-ffi": "~1.0.0", - "rindow/rindow-matlib-ffi": "~1.0.0", - "rindow/rindow-opencl-ffi": "~1.0.0", - "rindow/rindow-clblast-ffi": "~1.0.0" + "interop-phpobjects/polite-math": "~1.0.7", + "rindow/rindow-math-matrix": "~2.0.3", + "rindow/rindow-math-buffer-ffi": "~1.0.2", + "rindow/rindow-openblas-ffi": "~1.0.3", + "rindow/rindow-matlib-ffi": "~1.0.1", + "rindow/rindow-opencl-ffi": "~1.0.2", + "rindow/rindow-clblast-ffi": "~1.0.2" }, "suggest": { "rindow/rindow-math-plot": "for OpenCL tunning" diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..d7f8277 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - src diff --git a/src/MatlibFFI.php b/src/MatlibFFI.php index 4a9701c..ab94464 100644 --- a/src/MatlibFFI.php +++ b/src/MatlibFFI.php @@ -11,7 +11,7 @@ class MatlibFFI extends AbstractMatlibService { - protected $name = 'matlib_ffi'; + protected string $name = 'matlib_ffi'; public function __construct( object $bufferFactory=null, diff --git a/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/MatlibFFITest.php b/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/MatlibFFITest.php index a16921a..48efda8 100644 --- a/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/MatlibFFITest.php +++ b/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/MatlibFFITest.php @@ -61,7 +61,7 @@ public function testServiceLevel() if($this->isAvailable(['libopenblas.dll','libopenblas.so','libopenblas.so.0'])&& $this->isAvailable(['rindowmatlib.dll','librindowmatlib.so'])&& $this->isAvailable(['OpenCL.dll','libOpenCL.so.1'])&& - $this->isAvailable(['clblast.dll','libclblast.so'])&& + $this->isAvailable(['clblast.dll','libclblast.so.1'])&& class_exists('Rindow\Matlib\FFI\MatlibFactory')) { $this->assertEquals(Service::LV_ACCELERATED,$service->serviceLevel()); } elseif( @@ -69,7 +69,7 @@ class_exists('Rindow\Matlib\FFI\MatlibFactory')) { $this->isAvailable(['rindowmatlib.dll','librindowmatlib.so']) && class_exists('Rindow\Matlib\FFI\MatlibFactory') && (!$this->isAvailable(['OpenCL.dll','libOpenCL.so.1'])|| - !$this->isAvailable(['clblast.dll','libclblast.so'])|| + !$this->isAvailable(['clblast.dll','libclblast.so.1'])|| !class_exists('Rindow\OpenCL\FFI\OpenCLFactory'))) { $this->assertEquals(Service::LV_ADVANCED,$service->serviceLevel()); } elseif( diff --git a/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/SelectorTest.php b/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/SelectorTest.php new file mode 100644 index 0000000..5488ebf --- /dev/null +++ b/tests/RindowTest/Math/Matrix/Drivers/MatlibFFI/SelectorTest.php @@ -0,0 +1,82 @@ +newSelector(); + $service = $selector->select(); + if($ext != null) { + $extLevel = $ext->serviceLevel(); + } + if($ffi != null) { + $ffiLevel = $ffi->serviceLevel(); + } + + if($ffiLevel<=Service::LV_BASIC && $extLevel<=Service::LV_BASIC) { + $this->assertInstanceOf(MatlibPhp::class,$service); + } elseif($ffiLevel>$extLevel) { + $this->assertInstanceOf(MatlibFFI::class,$service); + } else { + $this->assertInstanceOf(MatlibExt::class,$service); + } + } + + public function testCatalog() + { + $classFFI = 'Rindow\Math\Matrix\Drivers\MatlibFFI\MatlibFFI'; + $classExt = 'Rindow\Math\Matrix\Drivers\MatlibExt\MatlibExt'; + $ffi = null; + if(class_exists($classFFI)) { + $ffi = new MatlibFFI(); + } + $ext = null; + if(class_exists($classExt)) { + $ext = new MatlibExt(); + } + $php = new MatlibPhp(); + + $truesrv = $php; + $level = Service::LV_BASIC; + if($ffi!==null && + $ffi->serviceLevel()>$level) { + $truesrv = $ffi; + $level = $ffi->serviceLevel(); + } + if($ext!==null && + $ext->serviceLevel()>$level) { + $truesrv = $ext; + $level = $ext->serviceLevel(); + } + $catalog = [$classFFI,$classExt,MatlibPhp::class]; + $selector = $this->newSelector($catalog); + $service = $selector->select(); + $this->assertInstanceOf(get_class($truesrv),$service); + } +} diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 42ef8f1..16266e1 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -5,5 +5,8 @@ ./RindowTest + + ../../rindow-math-matrix/tests/RindowTest +