blob: 303445449f4f0324c2f6a1ceba020a5df3d37d5d [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rsCpuIntrinsic.h"
#include "rsCpuIntrinsicInlines.h"
#include "cblas.h"
using namespace android;
using namespace android::renderscript;
namespace android {
namespace renderscript {
class RsdCpuScriptIntrinsicBLAS : public RsdCpuScriptIntrinsic {
public:
void invokeForEach(uint32_t slot,
const Allocation ** ain,
uint32_t inLen,
Allocation * aout,
const void * usr,
uint32_t usrLen,
const RsScriptCall *sc) override;
void populateScript(Script *) override;
~RsdCpuScriptIntrinsicBLAS() override;
RsdCpuScriptIntrinsicBLAS(RsdCpuReferenceImpl *ctx, const Script *s);
protected:
uint8_t a_offset = 0;
uint8_t b_offset = 0;
uint8_t c_offset = 0;
static void kernelBNNM(size_t m, size_t n, size_t k,
const uint8_t* a, uint32_t a_offset, size_t lda,
const uint8_t* b, uint32_t b_offset, size_t ldb,
uint8_t* c, uint32_t c_offset, size_t ldc,
uint32_t c_mult_int);
};
}
}
void RsdCpuScriptIntrinsicBLAS::populateScript(Script *s) {
s->mHal.info.exportedVariableCount = 0;
}
static void initABC(const Allocation ** ain,
size_t size,
void** A,
void** B,
void** C,
int* lda,
int* ldb,
int* ldc)
{
if (ain[0]) {
*A = ain[0]->mHal.drvState.lod[0].mallocPtr;
*lda = (int)(ain[0]->mHal.drvState.lod[0].stride/size);
}
if (ain[1]) {
*B = ain[1]->mHal.drvState.lod[0].mallocPtr;
*ldb = (int)(ain[1]->mHal.drvState.lod[0].stride/size);
}
if (ain[2]) {
*C = ain[2]->mHal.drvState.lod[0].mallocPtr;
*ldc = (int)(ain[2]->mHal.drvState.lod[0].stride/size);
}
}
void RsdCpuScriptIntrinsicBLAS::invokeForEach(uint32_t slot,
const Allocation ** ain,
uint32_t inLen,
Allocation * aout,
const void * usr,
uint32_t usrLen,
const RsScriptCall *sc) {
RsBlasCall* call = (RsBlasCall*) usr;
// setup BLAS enum args
enum CBLAS_TRANSPOSE TransA = (enum CBLAS_TRANSPOSE)call->transA;
enum CBLAS_TRANSPOSE TransB = (enum CBLAS_TRANSPOSE)call->transB;
enum CBLAS_UPLO Uplo = (enum CBLAS_UPLO)call->uplo;
enum CBLAS_DIAG Diag = (enum CBLAS_DIAG)call->diag;
enum CBLAS_SIDE Side = (enum CBLAS_SIDE)call->side;
void *A = nullptr;
void *B = nullptr;
void *C = nullptr;
void *X = nullptr;
void *Y = nullptr;
int lda = 0, ldb = 0, ldc = 0;
switch (call->func) {
// Level 1 BLAS: returns into a 1D Allocation
// Level 2 BLAS
case (RsBlas_sgemv):
initABC(ain, sizeof(float), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_sgemv(CblasRowMajor, TransA, call->M, call->N, call->alpha.f, (float*)A,
lda, (float*)X, call->incX, call->beta.f, (float*)Y, call->incY);
break;
case (RsBlas_sgbmv):
initABC(ain, sizeof(float), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_sgbmv(CblasRowMajor, TransA, call->M, call->N, call->KL, call->KU,
call->alpha.f, (float*)A, lda, (float*)X, call->incX,
call->beta.f, (float*)Y, call->incY);
break;
case (RsBlas_strmv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_strmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (float*)A,
lda, (float*)X, call->incX);
break;
case (RsBlas_stbmv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_stbmv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (float*)A,
lda, (float*)X, call->incX);
break;
// stpmv takes a packed 1D Allocation only
case (RsBlas_stpmv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_stpmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (float*)A,
(float*)X, call->incX);
break;
case (RsBlas_strsv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_strsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (float*)A, lda,
(float*)X, call->incX);
break;
case (RsBlas_stbsv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_stbsv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (float*)A,
lda, (float*)X, call->incX);
break;
case (RsBlas_stpsv):
initABC(ain, sizeof(float), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_stpsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (float*)A,
(float*)X, call->incX);
break;
case (RsBlas_dgemv):
initABC(ain, sizeof(double), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_dgemv(CblasRowMajor, TransA, call->M, call->N, call->alpha.d, (double*)A,
lda, (double*)X, call->incX, call->beta.d, (double*)Y, call->incY);
break;
case (RsBlas_dgbmv):
initABC(ain, sizeof(double), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_dgbmv(CblasRowMajor, TransA, call->M, call->N, call->KL, call->KU,
call->alpha.d, (double*)A, lda, (double*)X, call->incX,
call->beta.d, (double*)Y, call->incY);
break;
case (RsBlas_dtrmv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtrmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (double*)A,
lda, (double*)X, call->incX);
break;
case (RsBlas_dtbmv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtbmv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (double*)A,
lda, (double*)X, call->incX);
break;
// stpmv takes a packed 1D Allocation only
case (RsBlas_dtpmv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtpmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (double*)A,
(double*)X, call->incX);
break;
case (RsBlas_dtrsv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtrsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (double*)A, lda,
(double*)X, call->incX);
break;
case (RsBlas_dtbsv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtbsv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (double*)A,
lda, (double*)X, call->incX);
break;
case (RsBlas_dtpsv):
initABC(ain, sizeof(double), &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_dtpsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (double*)A,
(double*)X, call->incX);
break;
case (RsBlas_cgemv):
initABC(ain, sizeof(float)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_cgemv(CblasRowMajor, TransA, call->M, call->N, (void*)&call->alpha.c, (void*)A,
lda, (void*)X, call->incX, (void*)&call->beta.c, (void*)Y, call->incY);
break;
case (RsBlas_cgbmv):
initABC(ain, sizeof(float)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_cgbmv(CblasRowMajor, TransA, call->M, call->N, call->KL, call->KU,
(void*)&call->alpha.c, (void*)A, lda, (void*)X, call->incX,
(void*)&call->beta.c, (void*)Y, call->incY);
break;
case (RsBlas_ctrmv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctrmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
lda, (void*)X, call->incX);
break;
case (RsBlas_ctbmv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctbmv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (void*)A,
lda, (void*)X, call->incX);
break;
// stpmv takes a packed 1D Allocation only
case (RsBlas_ctpmv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctpmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
(void*)X, call->incX);
break;
case (RsBlas_ctrsv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctrsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A, lda,
(void*)X, call->incX);
break;
case (RsBlas_ctbsv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctbsv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (void*)A,
lda, (void*)X, call->incX);
break;
case (RsBlas_ctpsv):
initABC(ain, sizeof(float)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ctpsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
(void*)X, call->incX);
break;
case (RsBlas_zgemv):
initABC(ain, sizeof(double)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_zgemv(CblasRowMajor, TransA, call->M, call->N, (void*)&call->alpha.z, (void*)A,
lda, (void*)X, call->incX, (void*)&call->beta.z, (void*)Y, call->incY);
break;
case (RsBlas_zgbmv):
initABC(ain, sizeof(double)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_zgbmv(CblasRowMajor, TransA, call->M, call->N, call->KL, call->KU,
(void*)&call->alpha.z, (void*)A, lda, (void*)X, call->incX,
(void*)&call->beta.z, (void*)Y, call->incY);
break;
case (RsBlas_ztrmv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztrmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
lda, (void*)X, call->incX);
break;
case (RsBlas_ztbmv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztbmv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (void*)A,
lda, (void*)X, call->incX);
break;
// stpmv takes a packed 1D Allocation only
case (RsBlas_ztpmv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztpmv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
(void*)X, call->incX);
break;
case (RsBlas_ztrsv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztrsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A, lda,
(void*)X, call->incX);
break;
case (RsBlas_ztbsv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztbsv(CblasRowMajor, Uplo, TransA, Diag, call->N, call->K, (void*)A,
lda, (void*)X, call->incX);
break;
case (RsBlas_ztpsv):
initABC(ain, sizeof(double)*2, &A, &X, nullptr, &lda, &ldb, nullptr);
cblas_ztpsv(CblasRowMajor, Uplo, TransA, Diag, call->N, (void*)A,
(void*)X, call->incX);
break;
// S and D only
case (RsBlas_ssymv):
initABC(ain, sizeof(float), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_ssymv(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)A, lda,
(float*)X, call->incX, call->beta.f, (float*)Y, call->incY);
break;
case (RsBlas_ssbmv):
initABC(ain, sizeof(float), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_ssbmv(CblasRowMajor, Uplo, call->N, call->K, call->alpha.f,
(float*)A, lda, (float*)X, call->incX, call->beta.f,
(float*)Y, call->incY);
break;
//sspmv requires a packed 1D Allocation
case (RsBlas_sspmv):
initABC(ain, sizeof(float), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_sspmv(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)A,
(float*)X, call->incX, call->beta.f, (float*)Y, call->incY);
break;
// following calls have init reordered because A is output matrix
case (RsBlas_sger):
initABC(ain, sizeof(float), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_sger(CblasRowMajor, call->M, call->N, call->alpha.f, (float*)X,
call->incX, (float*)Y, call->incY, (float*)A, lda);
break;
case (RsBlas_ssyr):
initABC(ain, sizeof(float), &X, &A, nullptr, &ldb, &lda, nullptr);
cblas_ssyr(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)X, call->incX,
(float*)A, lda);
break;
// sspr is packed 1D Allocation A only
case (RsBlas_sspr):
initABC(ain, sizeof(float), &X, &A, nullptr, &ldb, &lda, nullptr);
cblas_sspr(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)X, call->incX,
(float*)A);
break;
case (RsBlas_ssyr2):
initABC(ain, sizeof(float), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_ssyr2(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)X, call->incX,
(float*)Y, call->incY, (float*)A, lda);
break;
// sspr2 is packed 1D Allocation A only
case (RsBlas_sspr2):
initABC(ain, sizeof(float), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_sspr2(CblasRowMajor, Uplo, call->N, call->alpha.f, (float*)X, call->incX,
(float*)Y, call->incY, (float*)A);
break;
case (RsBlas_dsymv):
initABC(ain, sizeof(double), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_dsymv(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)A, lda,
(double*)X, call->incX, call->beta.d, (double*)Y, call->incY);
break;
case (RsBlas_dsbmv):
initABC(ain, sizeof(double), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_dsbmv(CblasRowMajor, Uplo, call->N, call->K, call->alpha.d,
(double*)A, lda, (double*)X, call->incX, call->beta.d,
(double*)Y, call->incY);
break;
// dspmv requires a packed 1D Allocation
case (RsBlas_dspmv):
initABC(ain, sizeof(double), &A, &X, &Y, &lda, &ldb, &ldc);
cblas_dspmv(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)A,
(double*)X, call->incX, call->beta.d, (double*)Y, call->incY);
break;
// following calls have init reordered because A is output matrix
case (RsBlas_dger):
initABC(ain, sizeof(double), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_dger(CblasRowMajor, call->M, call->N, call->alpha.d, (double*)X,
call->incX, (double*)Y, call->incY, (double*)A, lda);
break;
case (RsBlas_dsyr):
initABC(ain, sizeof(double), &X, &A, nullptr, &ldb, &lda, nullptr);
cblas_dsyr(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)X, call->incX,
(double*)A, lda);
break;
// dspr is packed 1D Allocation A only
case (RsBlas_dspr):
initABC(ain, sizeof(double), &X, &A, nullptr, &ldb, &lda, nullptr);
cblas_dspr(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)X, call->incX,
(double*)A);
break;
case (RsBlas_dsyr2):
initABC(ain, sizeof(double), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_dsyr2(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)X, call->incX,
(double*)Y, call->incY, (double*)A, lda);
break;
// dspr2 is packed 1D Allocation A only
case (RsBlas_dspr2):
initABC(ain, sizeof(double), &X, &Y, &A, &ldb, &ldc, &lda);
cblas_dspr2(CblasRowMajor, Uplo, call->N, call->alpha.d, (double*)X, call->incX,
(double*)Y, call->incY, (double*)A);
break;
// C and Z only
case (RsBlas_chemv):
initABC(ain, sizeof(float)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_chemv(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.c, A, lda,
X, call->incX, (void*)&call->beta.c, Y, call->incY);
break;
case (RsBlas_chbmv):
initABC(ain, sizeof(float)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_chbmv(CblasRowMajor, Uplo, call->N, call->K, (void*)&call->alpha.c,
A, lda, X, call->incX, (void*)&call->beta.c, Y, call->incY);
break;
case (RsBlas_chpmv):
initABC(ain, sizeof(float)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_chpmv(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.c, A,
X, call->incX, (void*)&call->beta.c, Y, call->incY);
break;
case (RsBlas_cgeru):
initABC(ain, sizeof(float)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_cgeru(CblasRowMajor, call->M, call->N, (void*)&call->alpha.c,
X, call->incX, Y, call->incY, A, lda);
break;
case (RsBlas_cgerc):
initABC(ain, sizeof(float)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_cgerc(CblasRowMajor, call->M, call->N, (void*)&call->alpha.c,
X, call->incX, Y, call->incY, A, lda);
break;
case (RsBlas_cher):
initABC(ain, sizeof(float)*2, &X, nullptr, &A, &ldb, nullptr, &lda);
cblas_cher(CblasRowMajor, Uplo, call->N, call->alpha.f,
X, call->incX, A, lda);
break;
// packed 1D Allocations only
case (RsBlas_chpr):
initABC(ain, sizeof(float)*2, &X, nullptr, &A, &ldb, nullptr, &lda);
cblas_chpr(CblasRowMajor, Uplo, call->N, call->alpha.f, X,
call->incX, A);
break;
case (RsBlas_cher2):
initABC(ain, sizeof(float)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_cher2(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.c,
X, call->incX, Y, call->incY, A, lda);
break;
// packed 1D Allocations only
case (RsBlas_chpr2):
initABC(ain, sizeof(float)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_chpr2(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.c, X,
call->incX, Y, call->incY, A);
break;
case (RsBlas_zhemv):
initABC(ain, sizeof(double)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_zhemv(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.z, A, lda,
X, call->incX, (void*)&call->beta.z, Y, call->incY);
break;
case (RsBlas_zhbmv):
initABC(ain, sizeof(double)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_zhbmv(CblasRowMajor, Uplo, call->N, call->K, (void*)&call->alpha.z,
A, lda, X, call->incX, (void*)&call->beta.z, Y, call->incY);
break;
case (RsBlas_zhpmv):
initABC(ain, sizeof(double)*2, &A, &X, &Y, &lda, &ldb, &ldc);
cblas_zhpmv(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.z, A,
X, call->incX, (void*)&call->beta.z, Y, call->incY);
break;
case (RsBlas_zgeru):
initABC(ain, sizeof(double)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_zgeru(CblasRowMajor, call->M, call->N, (void*)&call->alpha.z,
X, call->incX, Y, call->incY, A, lda);
break;
case (RsBlas_zgerc):
initABC(ain, sizeof(double)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_zgerc(CblasRowMajor, call->M, call->N, (void*)&call->alpha.z,
X, call->incX, Y, call->incY, A, lda);
break;
case (RsBlas_zher):
initABC(ain, sizeof(double)*2, &X, nullptr, &A, &ldb, nullptr, &lda);
cblas_zher(CblasRowMajor, Uplo, call->N, call->alpha.d,
X, call->incX, A, lda);
break;
// packed 1D Allocations only
case (RsBlas_zhpr):
initABC(ain, sizeof(double)*2, &X, nullptr, &A, &ldb, nullptr, &lda);
cblas_zhpr(CblasRowMajor, Uplo, call->N, call->alpha.d, X,
call->incX, A);
break;
case (RsBlas_zher2):
initABC(ain, sizeof(double)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_zher2(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.z,
X, call->incX, Y, call->incY, A, lda);
break;
// packed 1D Allocations only
case (RsBlas_zhpr2):
initABC(ain, sizeof(double)*2, &X, &Y, &A, &ldb, &ldc, &lda);
cblas_zhpr2(CblasRowMajor, Uplo, call->N, (void*)&call->alpha.z, X,
call->incX, Y, call->incY, A);
break;
// Level 3 BLAS
case (RsBlas_sgemm):
initABC(ain, sizeof(float), &A, &B, &C, &lda, &ldb, &ldc);
cblas_sgemm(CblasRowMajor, TransA, TransB, call->M, call->N, call->K, call->alpha.f,
(float*)A, lda, (float*)B, ldb, call->beta.f, (float*)C, ldc);
break;
case (RsBlas_ssymm):
initABC(ain, sizeof(float), &A, &B, &C, &lda, &ldb, &ldc);
cblas_ssymm(CblasRowMajor, Side, Uplo, call->M, call->N, call->alpha.f, (float*)A,
lda, (float*)B, ldb, call->beta.f, (float*)C, ldc);
break;
case (RsBlas_ssyrk):
initABC(ain, sizeof(float), &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_ssyrk(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.f, (float*)A,
lda, call->beta.f, (float*)C, ldc);
break;
case (RsBlas_ssyr2k):
initABC(ain, sizeof(float), &A, &B, &C, &lda, &ldb, &ldc);
cblas_ssyr2k(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.f, (float*)A,
lda, (float*)B, ldb, call->beta.f, (float*)C, ldc);
break;
case (RsBlas_strmm):
initABC(ain, sizeof(float), &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_strmm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, call->alpha.f,
(float*)A, lda, (float*)B, ldb);
break;
case (RsBlas_strsm):
initABC(ain, sizeof(float), &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_strsm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, call->alpha.f,
(float*)A, lda, (float*)B, ldb);
break;
case (RsBlas_dgemm):
initABC(ain, sizeof(double), &A, &B, &C, &lda, &ldb, &ldc);
cblas_dgemm(CblasRowMajor, TransA, TransB, call->M, call->N, call->K, call->alpha.d,
(double*)A, lda, (double*)B, ldb, call->beta.d, (double*)C, ldc);
break;
case (RsBlas_dsymm):
initABC(ain, sizeof(double), &A, &B, &C, &lda, &ldb, &ldc);
cblas_dsymm(CblasRowMajor, Side, Uplo, call->M, call->N, call->alpha.d, (double*)A,
lda, (double*)B, ldb, call->beta.d, (double*)C, ldc);
break;
case (RsBlas_dsyrk):
initABC(ain, sizeof(double), &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_dsyrk(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.d, (double*)A,
lda, call->beta.d, (double*)C, ldc);
break;
case (RsBlas_dsyr2k):
initABC(ain, sizeof(double), &A, &B, &C, &lda, &ldb, &ldc);
cblas_dsyr2k(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.d, (double*)A,
lda, (double*)B, ldb, call->beta.d, (double*)C, ldc);
break;
case (RsBlas_dtrmm):
initABC(ain, sizeof(double), &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_dtrmm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, call->alpha.d,
(double*)A, lda, (double*)B, ldb);
break;
case (RsBlas_dtrsm):
initABC(ain, sizeof(double), &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_dtrsm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, call->alpha.d,
(double*)A, lda, (double*)B, ldb);
break;
case (RsBlas_cgemm):
initABC(ain, sizeof(float)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_cgemm(CblasRowMajor, TransA, TransB, call->M, call->N, call->K, (void*)&call->alpha.c,
A, lda, B, ldb, (void*)&call->beta.c, C, ldc);
break;
case (RsBlas_csymm):
initABC(ain, sizeof(float)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_csymm(CblasRowMajor, Side, Uplo, call->M, call->N, (void*)&call->alpha.c, A,
lda, B, ldb, (void*)&call->beta.c, C, ldc);
break;
case (RsBlas_csyrk):
initABC(ain, sizeof(float)*2, &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_csyrk(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.c, A,
lda, (void*)&call->beta.c, C, ldc);
break;
case (RsBlas_csyr2k):
initABC(ain, sizeof(float)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_csyr2k(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.c, A,
lda, B, ldb, (void*)&call->beta.c, C, ldc);
break;
case (RsBlas_ctrmm):
initABC(ain, sizeof(float)*2, &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_ctrmm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, (void*)&call->alpha.c,
A, lda, B, ldb);
break;
case (RsBlas_ctrsm):
initABC(ain, sizeof(float)*2, &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_ctrsm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, (void*)&call->alpha.c,
A, lda, B, ldb);
break;
case (RsBlas_zgemm):
initABC(ain, sizeof(double)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_zgemm(CblasRowMajor, TransA, TransB, call->M, call->N, call->K, (void*)&call->alpha.z,
A, lda, B, ldb, (void*)&call->beta.z, C, ldc);
break;
case (RsBlas_zsymm):
initABC(ain, sizeof(double)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_zsymm(CblasRowMajor, Side, Uplo, call->M, call->N, (void*)&call->alpha.z, A,
lda, B, ldb, (void*)&call->beta.z, C, ldc);
break;
case (RsBlas_zsyrk):
initABC(ain, sizeof(double)*2, &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_zsyrk(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.z, A,
lda, (void*)&call->beta.z, C, ldc);
break;
case (RsBlas_zsyr2k):
initABC(ain, sizeof(double)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_zsyr2k(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.z, A,
lda, B, ldb, (void*)&call->beta.z, C, ldc);
break;
case (RsBlas_ztrmm):
initABC(ain, sizeof(double)*2, &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_ztrmm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, (void*)&call->alpha.z,
A, lda, B, ldb);
break;
case (RsBlas_ztrsm):
initABC(ain, sizeof(double)*2, &A, &B, nullptr, &lda, &ldb, nullptr);
cblas_ztrsm(CblasRowMajor, Side, Uplo, TransA, Diag, call->M, call->N, (void*)&call->alpha.z,
A, lda, B, ldb);
break;
// Level 3 C and Z only
case (RsBlas_chemm):
initABC(ain, sizeof(float)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_chemm(CblasRowMajor, Side, Uplo, call->M, call->N, (void*)&call->alpha.c, A, lda,
B, ldb, (void*)&call->beta.c, C, ldc);
break;
case (RsBlas_cherk):
initABC(ain, sizeof(float)*2, &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_cherk(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.f, A, lda,
call->beta.f, C, ldc);
break;
case (RsBlas_cher2k):
initABC(ain, sizeof(float)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_cher2k(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.c, A, lda,
B, ldb, call->beta.f, C, ldc);
break;
case (RsBlas_zhemm):
initABC(ain, sizeof(double)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_zhemm(CblasRowMajor, Side, Uplo, call->M, call->N, (void*)&call->alpha.z, A, lda,
B, ldb, (void*)&call->beta.z, C, ldc);
break;
case (RsBlas_zherk):
initABC(ain, sizeof(double)*2, &A, nullptr, &C, &lda, nullptr, &ldc);
cblas_zherk(CblasRowMajor, Uplo, TransA, call->N, call->K, call->alpha.d, A, lda,
call->beta.d, C, ldc);
break;
case (RsBlas_zher2k):
initABC(ain, sizeof(double)*2, &A, &B, &C, &lda, &ldb, &ldc);
cblas_zher2k(CblasRowMajor, Uplo, TransA, call->N, call->K, (void*)&call->alpha.z, A, lda,
B, ldb, call->beta.d, C, ldc);
break;
case (RsBlas_bnnm):
initABC(ain, sizeof(uint8_t), &A, &B, &C, &lda, &ldb, &ldc);
kernelBNNM(call->M, call->N, call->K,
(const uint8_t*)A, call->a_offset, lda,
(const uint8_t*)B, call->b_offset, ldb,
(uint8_t*)C, call->c_offset, ldc,
call->c_mult_int);
break;
default:
ALOGE("unimplemented\n");
}
}
void RsdCpuScriptIntrinsicBLAS::kernelBNNM(size_t m, size_t n, size_t k,
const uint8_t* a, uint32_t a_offset, size_t lda,
const uint8_t* b, uint32_t b_offset, size_t ldb,
uint8_t* c, uint32_t c_offset, size_t ldc,
uint32_t c_mult_int) {
// Calculations are done in 1.10.21 fixed-point format for the final output,
// just before there's a shift down to drop the fractional parts. The output
// values are gated to 0 to 255 to fit in a byte, but the 10-bit format
// gives some headroom to avoid wrapping around on small overflows.
const int c_shift = 21;
size_t i = 0, j = 0, l = 0;
for (j = 0; j < n; j++) {
for (i = 0; i < m; i++) {
int32_t total = 0;
for (l = 0; l < k; l++) {
const int a_index = ((i * lda) + l);
const uint8_t a_as_byte = a[a_index];
const int32_t a_as_int = (((int32_t)(a_as_byte)) - a_offset);
const int b_index = ((j * ldb) + l);
const uint8_t b_as_byte = b[b_index];
const int32_t b_as_int = (((int32_t)(b_as_byte)) - b_offset);
const int32_t mult_as_int = (a_as_int * b_as_int);
total += mult_as_int;
}
const int c_index = ((ldc * i) + j);
int32_t output =
((((total + c_offset) * c_mult_int) + (1 << (c_shift - 1)))
>> c_shift);
if (output > 255) {
output = 255;
}
if (output < 0) {
output = 0;
}
c[c_index] = (uint8_t)(output);
}
}
}
RsdCpuScriptIntrinsicBLAS::RsdCpuScriptIntrinsicBLAS(RsdCpuReferenceImpl *ctx,
const Script *s)
: RsdCpuScriptIntrinsic(ctx, s, nullptr, RS_SCRIPT_INTRINSIC_ID_BLAS) {
}
RsdCpuScriptIntrinsicBLAS::~RsdCpuScriptIntrinsicBLAS() {
}
RsdCpuScriptImpl * rsdIntrinsic_BLAS(RsdCpuReferenceImpl *ctx,
const Script *s, const Element *e) {
return new RsdCpuScriptIntrinsicBLAS(ctx, s);
}