Array buffer

Concepts

PHP’s Array type is not suitable for matrix operations. We need a common format. It exchanges data between C language programs that realize high-speed matrix operations and PHP programs that handle matrix operations.

In general, fast matrix operations use a contiguous memory area that stores numbers. For example, if you want to use the SIMD instruction of the CPU, or a data area to transfer to the GPU.

The Buffer class can handle a continuous memory area as an array in PHP.

The memory area can be accessed from PHP as a one-dimensional array. The data is just a single sequence of numbers.

How you use it as an N-dimensional array is up to the program that uses it. This allows it to be defined as a simple specification.

PHP interface

Buffer is created by specifying data type and size. Since it has an ArrayAccess interface and a Count interface, it can be used like an array.

The universal Buffer has the following interface for convenience:

use Interop\Polite\Math\Matrix\Buffer as BufferInterface;

class Buffer implements BufferInterface {
    public function __construct(int $size, int $dtype);
    public function dtype() : int;
    public function value_size() : int;
    public function count() : int;
    public function offsetExists(mixed $offset) : bool;
    public function offsetGet(mixed $offset): mixed;
    public function offsetSet(mixed $offset, mixed $value): void;
    public function offsetUnset(mixed $offset): void;
    public function dump() : string;
    public function load(string $string) : void;
}

The definition of the Buffer interface is as follows.

namespace Interop\Polite\Math\Matrix;

use Countable;
use ArrayAccess;

interface BufferInterface extends Countable,ArrayAccess
{
}

To enable a C language interface, rindow-math-buffer-ffi via FFI adds a LinearBuffer interface that inherits from Buffer and an addr method.

LinearBuffer represents a continuous memory space buffer such as in C language.

namespace Rindow\Math\Buffer\FFI;
use Interop\Polite\Math\Matrix\LinearBuffer;
use FFI;

class Buffer implements LinearBuffer {
    public function __construct(int $size, int $dtype);
    public function dtype() : int;
    public function value_size() : int;
    public function count() : int;
    public function addr(int $offset) : FFI\CData
    public function offsetExists(mixed $offset) : bool;
    public function offsetGet(mixed $offset): mixed;
    public function offsetSet(mixed $offset, mixed $value): void;
    public function offsetUnset(mixed $offset): void;
    public function dump() : string;
    public function load(string $string) : void;
}

To standardize the interface, be sure to use a factory to generate objects.

namespace Rindow\Math\Buffer\FFI;

class BufferFactory
{
    public function isAvailable() : bool;
    public function Buffer(int $size, int $dtype) : Buffer;
}

Usage on PHP

Here is the sample code.

use Interop\Polite\Math\Matrix\NDArray;
$factory = new Rindow\Math\Buffer\FFI\BufferFactory()
$buffer = $factory->Buffer(10,NDArray::float32);
$buffer[0] = 1.0;
$buffer[1] = 1.5;
$x = $buffer[0]+$buffer[1];
$count = count($buffer);

You can quickly dump the data in the buffer.

$x = $factory->Buffer(10,NDArray::float32);
$y = $factory->Buffer(10,NDArray::float32);
$x[0] = 1.0;
$x[1] = 1.5;
$data = $x->dump();
$y->load($data);