Skip to content

Commit c7b64f6

Browse files
committed
add blas functions
1 parent 5c21edd commit c7b64f6

8 files changed

+1860
-2
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,12 @@ Please see the documents on [Rindow projects](https://rindow.github.io/) web pag
2020

2121
You can perform very fast N-dimensional array operations in conjunction
2222

23-
- [Pre-build binaries](https://github.com/rindow/rindow-openblas-binaries)
23+
- [Pre-build binaries](https://github.com/rindow/rindow-openblas/releases)
2424
- [Build from source](https://github.com/rindow/rindow-openblas)
25+
26+
### Acceleration with GPU
27+
28+
You can use GPU acceleration on OpenCL.
29+
30+
- [Pre-build binaries](https://github.com/rindow/rindow-clblast/releases)
31+
- [Build from source](https://github.com/rindow/rindow-clblast)

composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"interop-phpobjects/polite-math": ">=1.0.3"
1010
},
1111
"suggest": {
12-
"ext-rindow_openblas": "0.1.6 strongly recommended for speed",
12+
"ext-rindow_openblas": "0.2.0 strongly recommended for speed",
13+
"ext-rindow_opencl": "0.1.0 GPU/OpenCL support",
14+
"ext-rindow_clblast": "0.1.1 BLAS on GPU/OpenCL support",
1315
"rindow/math-plot": "for OpenCL tunning"
1416
},
1517
"autoload": {

src/LinearAlgebra.php

+303
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,309 @@ public function matmul(
662662
return $C;
663663
}
664664

665+
/**
666+
* A = Symmetric matrix
667+
* C := alpha * AB + beta * C ( right = false )
668+
* C := alpha * BA + beta * C ( right = true )
669+
*/
670+
public function symm(
671+
NDArray $A,
672+
NDArray $B,
673+
float $alpha=null,
674+
float $beta=null,
675+
NDArray $C=null,
676+
bool $right=null,
677+
bool $lower=null
678+
) : NDArray
679+
{
680+
if($A->ndim()!=2 || $B->ndim()!=2) {
681+
throw new InvalidArgumentException('Dimensions must be 2D-NDArray');
682+
}
683+
$shapeA = $A->shape();
684+
$rowsA = $shapeA[0];
685+
if($rowsA!=$shapeA[1]) {
686+
throw new InvalidArgumentException('The matrix "A" must be symmetric');
687+
}
688+
$shapeB = $B->shape();
689+
$M = $shapeB[0];
690+
$N = $shapeB[1];
691+
$tmpB = ($right) ? $N : $M;
692+
if($rowsA!=$tmpB) {
693+
throw new InvalidArgumentException('Unmatch Shape of matrix "A" and "B": '."($rowsA,$rowsA) != ($M,$N)");
694+
}
695+
$AA = $A->buffer();
696+
$BB = $B->buffer();
697+
$offA = $A->offset();
698+
$offB = $B->offset();
699+
700+
if($alpha===null) {
701+
$alpha = 1.0;
702+
}
703+
if($beta===null) {
704+
$beta = 0.0;
705+
}
706+
if($C!=null) {
707+
$shapeC = $C->shape();
708+
if($M!=$shapeC[0] || $N!=$shapeC[1]) {
709+
throw new InvalidArgumentException('Matrix "B" and "C" must be same shape');
710+
}
711+
} else {
712+
$C = $this->zeros($this->alloc([$M,$N],$A->dtype()));
713+
}
714+
$CC = $C->buffer();
715+
$offC = $C->offset();
716+
717+
$lda = $rowsA;
718+
$ldb = $N;
719+
$ldc = $N;
720+
$side = ($right) ? BLAS::Right : BLAS::Left;
721+
$uplo = ($lower) ? BLAS::Lower : BLAS::Upper;
722+
723+
$this->blas->symm(
724+
BLAS::RowMajor,$side,$uplo,
725+
$M,$N,
726+
$alpha,
727+
$AA,$offA,$lda,
728+
$BB,$offB,$ldb,
729+
$beta,
730+
$CC,$offC,$ldc);
731+
732+
return $C;
733+
}
734+
735+
/**
736+
* C := alpha * A A^T + beta * C (trans=false)
737+
* C := alpha * A^T A + beta * C (trans=true)
738+
*/
739+
public function syrk(
740+
NDArray $A,
741+
float $alpha=null,
742+
float $beta=null,
743+
NDArray $C=null,
744+
bool $lower=null,
745+
bool $trans=null) : NDArray
746+
{
747+
if($A->ndim()!=2) {
748+
throw new InvalidArgumentException('Dimensions must be 2D-NDArray');
749+
}
750+
$shapeA = $A->shape();
751+
if($trans) {
752+
$shapeA = [$shapeA[1],$shapeA[0]];
753+
}
754+
$AA = $A->buffer();
755+
$offA = $A->offset();
756+
$N = $shapeA[0];
757+
$K = $shapeA[1];
758+
759+
if($alpha===null) {
760+
$alpha = 1.0;
761+
}
762+
if($beta===null) {
763+
$beta = 0.0;
764+
}
765+
if($C!=null) {
766+
$shapeC = $C->shape();
767+
if($N!=$shapeC[0] || $N!=$shapeC[1]) {
768+
throw new InvalidArgumentException('"C" rows and cols must have the same number of "A" cols');
769+
}
770+
} else {
771+
$C = $this->zeros($this->alloc([$N,$N],$A->dtype()));
772+
}
773+
$CC = $C->buffer();
774+
$offC = $C->offset();
775+
776+
$lda = ($trans) ? $N : $K;
777+
$ldc = $N;
778+
$uplo = ($lower) ? BLAS::Lower : BLAS::Upper;
779+
$trans = ($trans) ? BLAS::Trans : BLAS::NoTrans;
780+
781+
$this->blas->syrk(
782+
BLAS::RowMajor,$uplo,$trans,
783+
$N,$K,
784+
$alpha,
785+
$AA,$offA,$lda,
786+
$beta,
787+
$CC,$offC,$ldc);
788+
789+
return $C;
790+
}
791+
792+
/**
793+
* C := alpha * A B^T + B A^T + beta * C (trans=false)
794+
* C := alpha * B^T A + A B^T + beta * C (trans=true)
795+
*/
796+
public function syr2k(
797+
NDArray $A,
798+
NDArray $B,
799+
float $alpha=null,
800+
float $beta=null,
801+
NDArray $C=null,
802+
bool $lower=null,
803+
bool $trans=null) : NDArray
804+
{
805+
if($A->ndim()!=2 || $B->ndim()!=2) {
806+
throw new InvalidArgumentException('Dimensions must be 2D-NDArray');
807+
}
808+
$shapeA = $A->shape();
809+
$shapeB = $B->shape();
810+
if($shapeA!=$shapeB) {
811+
throw new InvalidArgumentException('Matrix A and B must be same shape');
812+
}
813+
if($trans) {
814+
$shapeA = [$shapeA[1],$shapeA[0]];
815+
}
816+
$AA = $A->buffer();
817+
$offA = $A->offset();
818+
$BB = $B->buffer();
819+
$offB = $B->offset();
820+
$N = $shapeA[0];
821+
$K = $shapeA[1];
822+
823+
if($alpha===null) {
824+
$alpha = 1.0;
825+
}
826+
if($beta===null) {
827+
$beta = 0.0;
828+
}
829+
if($C!=null) {
830+
$shapeC = $C->shape();
831+
if($N!=$shapeC[0] || $N!=$shapeC[1]) {
832+
throw new InvalidArgumentException('"C" rows and cols must have the same number of "A" cols');
833+
}
834+
} else {
835+
$C = $this->zeros($this->alloc([$N,$N],$A->dtype()));
836+
}
837+
$CC = $C->buffer();
838+
$offC = $C->offset();
839+
840+
$lda = ($trans) ? $N : $K;
841+
$ldb = ($trans) ? $N : $K;
842+
$ldc = $N;
843+
$uplo = ($lower) ? BLAS::Lower : BLAS::Upper;
844+
$trans = ($trans) ? BLAS::Trans : BLAS::NoTrans;
845+
846+
$this->blas->syr2k(
847+
BLAS::RowMajor,$uplo,$trans,
848+
$N,$K,
849+
$alpha,
850+
$AA,$offA,$lda,
851+
$BB,$offB,$ldb,
852+
$beta,
853+
$CC,$offC,$ldc);
854+
855+
return $C;
856+
}
857+
858+
/**
859+
* C := alpha * A B (right=false)
860+
* C := alpha * B A (right=true)
861+
*/
862+
public function trmm(
863+
NDArray $A,
864+
NDArray $B,
865+
float $alpha=null,
866+
bool $right=null,
867+
bool $lower=null,
868+
bool $trans=null,
869+
bool $unit=null) : NDArray
870+
{
871+
if($A->ndim()!=2 || $B->ndim()!=2) {
872+
throw new InvalidArgumentException('Dimensions must be 2D-NDArray');
873+
}
874+
$shapeA = $A->shape();
875+
$shapeB = $B->shape();
876+
if($right) {
877+
$sizeA = $shapeB[1];
878+
} else {
879+
$sizeA = $shapeB[0];
880+
}
881+
if($sizeA!=$shapeA[0]) {
882+
throw new InvalidArgumentException('Unmatch shape of Matrix A and B: '.
883+
'['.implode(',',$shapeA).'] <=> ['.implode(',',$shapeA).']');
884+
}
885+
$AA = $A->buffer();
886+
$offA = $A->offset();
887+
$BB = $B->buffer();
888+
$offB = $B->offset();
889+
$M = $shapeB[0];
890+
$N = $shapeB[1];
891+
892+
if($alpha===null) {
893+
$alpha = 1.0;
894+
}
895+
896+
$lda = ($right) ? $N : $M;
897+
$ldb = $N;
898+
$side = ($right) ? BLAS::Right : BLAS::Left;
899+
$uplo = ($lower) ? BLAS::Lower : BLAS::Upper;
900+
$trans = ($trans) ? BLAS::Trans : BLAS::NoTrans;
901+
$diag = ($unit) ? BLAS::Unit : BLAS::NonUnit;
902+
903+
$this->blas->trmm(
904+
BLAS::RowMajor,$side,$uplo,$trans,$diag,
905+
$M,$N,
906+
$alpha,
907+
$AA,$offA,$lda,
908+
$BB,$offB,$ldb);
909+
910+
return $B;
911+
}
912+
913+
/**
914+
* C := alpha A^-1 B (right=false)
915+
* C := alpha B A^-1 (right=true)
916+
*/
917+
public function trsm(
918+
NDArray $A,
919+
NDArray $B,
920+
float $alpha=null,
921+
bool $right=null,
922+
bool $lower=null,
923+
bool $trans=null,
924+
bool $unit=null) : NDArray
925+
{
926+
if($A->ndim()!=2 || $B->ndim()!=2) {
927+
throw new InvalidArgumentException('Dimensions must be 2D-NDArray');
928+
}
929+
$shapeA = $A->shape();
930+
$shapeB = $B->shape();
931+
if($right) {
932+
$sizeA = $shapeB[1];
933+
} else {
934+
$sizeA = $shapeB[0];
935+
}
936+
if($sizeA!=$shapeA[0]) {
937+
throw new InvalidArgumentException('Unmatch shape of Matrix A and B: '.
938+
'['.implode(',',$shapeA).'] <=> ['.implode(',',$shapeA).']');
939+
}
940+
$AA = $A->buffer();
941+
$offA = $A->offset();
942+
$BB = $B->buffer();
943+
$offB = $B->offset();
944+
$M = $shapeB[0];
945+
$N = $shapeB[1];
946+
947+
if($alpha===null) {
948+
$alpha = 1.0;
949+
}
950+
951+
$lda = ($right) ? $N : $M;
952+
$ldb = $N;
953+
$side = ($right) ? BLAS::Right : BLAS::Left;
954+
$uplo = ($lower) ? BLAS::Lower : BLAS::Upper;
955+
$trans = ($trans) ? BLAS::Trans : BLAS::NoTrans;
956+
$diag = ($unit) ? BLAS::Unit : BLAS::NonUnit;
957+
958+
$this->blas->trsm(
959+
BLAS::RowMajor,$side,$uplo,$trans,$diag,
960+
$M,$N,
961+
$alpha,
962+
$AA,$offA,$lda,
963+
$BB,$offB,$ldb);
964+
965+
return $B;
966+
}
967+
665968
/**
666969
* ret := x_1 + ... + x_n
667970
*/

0 commit comments

Comments
 (0)