From 2623eed83efaf6a7f86e2e4bcbc32d4740e69b69 Mon Sep 17 00:00:00 2001 From: Yuichi Ishikawa Date: Tue, 21 May 2024 08:42:39 +0900 Subject: [PATCH] allocate aligned size --- .github/workflows/tests.yml | 10 ++- arch.txt | 13 +++ src/Buffer.php | 16 +++- src/BufferNoHeader.php | 88 ------------------- .../Math/Matrix/Buffer/FFI/BufferTest.php | 62 +++++++------ 5 files changed, 68 insertions(+), 121 deletions(-) create mode 100644 arch.txt delete mode 100644 src/BufferNoHeader.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 233d50a..f3d752c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,9 +13,6 @@ jobs: fail-fast: true matrix: include: - - name: macOS - os: macos-latest - php: '8.3' - name: PHP8.1 os: ubuntu-latest php: '8.1' @@ -28,6 +25,12 @@ jobs: - name: Windows os: windows-latest php: '8.3' + - name: macOS + os: macos-latest + php: '8.3' + - name: macOS-x86_64 + os: macos-13 + php: '8.3' steps: - name: Setup PHP ${{ matrix.php }} @@ -71,4 +74,3 @@ jobs: - name: PHPUnit Tests run: phpunit -c tests - diff --git a/arch.txt b/arch.txt new file mode 100644 index 0000000..33f63c5 --- /dev/null +++ b/arch.txt @@ -0,0 +1,13 @@ + + +Linux amd64 +Linux fv-az1106-239 6.5.0-1021-azure #22~22.04.1-Ubuntu SMP Tue Apr 30 16:08:18 UTC 2024 x86_64 + +Windows x64 +Windows NT fv-az653-785 10.0 build 20348 (Windows Server 2022) AMD64 + +Intel Mac +Darwin Mac-1716203764718.local 22.6.0 Darwin Kernel Version 22.6.0: Mon Feb 19 19:48:53 PST 2024; root:xnu-8796.141.3.704.6~1/RELEASE_X86_64 x86_64 + +M1 Mac +Darwin Mac-1716204565015.local 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:10:50 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_VMAPPLE arm64 diff --git a/src/Buffer.php b/src/Buffer.php index efbfdcc..1909831 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -72,7 +72,8 @@ public function __construct(int $size, int $dtype) } if (self::$ffi === null) { - $code = @file_get_contents(__DIR__ . '/buffer.h'); + $header = __DIR__ . '/buffer.h'; + $code = @file_get_contents($header); if ($code === false) { throw new RuntimeException("Unable to read buffer.h file"); } @@ -89,9 +90,19 @@ public function __construct(int $size, int $dtype) $this->size = $size; $this->dtype = $dtype; $declaration = self::$typeString[$dtype]; + $size = $this->aligned($size,$dtype,16); // 128bit $this->data = self::$ffi->new("{$declaration}[{$size}]"); } + protected function aligned(int $size, int $dtype,int $base) : int + { + $valueSize = self::$valueSize[$dtype]; + $bytes = $size*$valueSize; + $alignedBytes = intdiv(($bytes+$base-1),$base)*$base; + $alignedSize = intdiv(($alignedBytes+$valueSize-1),$valueSize)*$valueSize; + return $alignedSize; + } + protected function assertOffset(string $method, mixed $offset) : void { if(!is_int($offset)) { @@ -181,7 +192,8 @@ public function offsetUnset(mixed $offset): void public function dump() : string { $byte = self::$valueSize[$this->dtype] * $this->size; - $buf = self::$ffi->new("char[$byte]"); + $alignedBytes = $this->aligned($byte,NDArray::int8,128); + $buf = self::$ffi->new("char[$alignedBytes]"); FFI::memcpy($buf,$this->data,$byte); return FFI::string($buf,$byte); } diff --git a/src/BufferNoHeader.php b/src/BufferNoHeader.php deleted file mode 100644 index 4939791..0000000 --- a/src/BufferNoHeader.php +++ /dev/null @@ -1,88 +0,0 @@ -=$limitsize) { - throw new InvalidArgumentException("Data size is too large."); - } - $this->size = $size; - $this->dtype = $dtype; - switch($dtype) { - case NDArray::complex64: { - $declaration = parent::$typeString[NDArray::float32]; - $size *= 2; - break; - } - case NDArray::complex128: { - $declaration = parent::$typeString[NDArray::float64]; - $size *= 2; - break; - } - default: { - $declaration = parent::$typeString[$dtype]; - break; - } - } - $this->data = parent::$ffi->new("{$declaration}[{$size}]"); - } - - public function addr(int $offset) : FFI\CData - { - if($this->isComplex()) { - $offset *= 2; - } - return FFI::addr($this->data[$offset]); - } - - public function offsetGet(mixed $offset): mixed - { - $this->assertOffset('offsetGet',$offset); - if($this->isComplex()) { - $offset *= 2; - $real = $this->data[$offset]; - $imag = $this->data[$offset+1]; - $value = (object)['real'=>$real,'imag'=>$imag]; - } else { - $value = $this->data[$offset]; - } - if($this->dtype===NDArray::bool) { - $value = $value ? true : false; - } - return $value; - } - - public function offsetSet(mixed $offset, mixed $value): void - { - $this->assertOffset('offsetSet',$offset); - if($this->isComplex()) { - if(is_array($value)) { - [$real,$imag] = $value; - } elseif(is_object($value)) { - $real = $value->real; - $imag = $value->imag; - } else { - $type = gettype($value); - throw new InvalidArgumentException("Cannot convert to complex number.: ".$type); - } - $offset *= 2; - $this->data[$offset] = $real; - $this->data[$offset+1] = $imag; - } else { - $this->data[$offset] = $value; - } - } -} diff --git a/tests/RindowTest/Math/Matrix/Buffer/FFI/BufferTest.php b/tests/RindowTest/Math/Matrix/Buffer/FFI/BufferTest.php index efef1ec..f2f5efe 100644 --- a/tests/RindowTest/Math/Matrix/Buffer/FFI/BufferTest.php +++ b/tests/RindowTest/Math/Matrix/Buffer/FFI/BufferTest.php @@ -21,6 +21,12 @@ public function setUp() : void $this->factory = new BufferFactory(); } + protected function notSupportComplex() : bool + { + //return PHP_OS==='Darwin'; + return false; + } + //public function testExtensionVersion() //{ // $this->assertEquals('0.1.7',phpversion('rindow_openblas')); @@ -108,33 +114,35 @@ public function testDtypesAndOffsetOfDtypes() $this->assertTrue(is_float($buf[0])); $this->assertEquals(0.5,$buf[2]); - $buf = $this->factory->Buffer(3,NDArray::complex64); - $this->assertEquals(NDArray::complex64,$buf->dtype()); - $this->assertEquals(3,count($buf)); - $this->assertEquals(8,$buf->value_size()); - $this->assertEquals(NDArray::complex64,$buf->dtype()); - $buf[1] = [1.5,2.5]; - $buf[2] = (object)['real'=>3.5,'imag'=>4.5]; - $vv = $buf[1]; - $this->assertEquals(1.5,$vv->real); - $this->assertEquals(2.5,$vv->imag); - $vv = $buf[2]; - $this->assertEquals(3.5,$vv->real); - $this->assertEquals(4.5,$vv->imag); - - $buf = $this->factory->Buffer(3,NDArray::complex128); - $this->assertEquals(NDArray::complex128,$buf->dtype()); - $this->assertEquals(3,count($buf)); - $this->assertEquals(16,$buf->value_size()); - $this->assertEquals(NDArray::complex128,$buf->dtype()); - $buf[1] = [1.5,2.5]; - $buf[2] = (object)['real'=>3.5,'imag'=>4.5]; - $vv = $buf[1]; - $this->assertEquals(1.5,$vv->real); - $this->assertEquals(2.5,$vv->imag); - $vv = $buf[2]; - $this->assertEquals(3.5,$vv->real); - $this->assertEquals(4.5,$vv->imag); + if(!$this->notSupportComplex()) { + $buf = $this->factory->Buffer(3,NDArray::complex64); + $this->assertEquals(NDArray::complex64,$buf->dtype()); + $this->assertEquals(3,count($buf)); + $this->assertEquals(8,$buf->value_size()); + $this->assertEquals(NDArray::complex64,$buf->dtype()); + $buf[1] = [1.5,2.5]; + $buf[2] = (object)['real'=>3.5,'imag'=>4.5]; + $vv = $buf[1]; + $this->assertEquals(1.5,$vv->real); + $this->assertEquals(2.5,$vv->imag); + $vv = $buf[2]; + $this->assertEquals(3.5,$vv->real); + $this->assertEquals(4.5,$vv->imag); + + $buf = $this->factory->Buffer(3,NDArray::complex128); + $this->assertEquals(NDArray::complex128,$buf->dtype()); + $this->assertEquals(3,count($buf)); + $this->assertEquals(16,$buf->value_size()); + $this->assertEquals(NDArray::complex128,$buf->dtype()); + $buf[1] = [1.5,2.5]; + $buf[2] = (object)['real'=>3.5,'imag'=>4.5]; + $vv = $buf[1]; + $this->assertEquals(1.5,$vv->real); + $this->assertEquals(2.5,$vv->imag); + $vv = $buf[2]; + $this->assertEquals(3.5,$vv->real); + $this->assertEquals(4.5,$vv->imag); + } } public function testOffsetExists()