26 #include "blas_impl.hpp"
27 #include "code_generator.hpp"
28 #include "global_options.hpp"
29 #include "runtime/casadi_runtime.hpp"
48 casadi_daxpy_t casadi_daxpy_hook =
nullptr;
49 casadi_ddot_t casadi_ddot_hook =
nullptr;
50 casadi_dscal_t casadi_dscal_hook =
nullptr;
51 casadi_dnrm2_t casadi_dnrm2_hook =
nullptr;
52 casadi_dasum_t casadi_dasum_hook =
nullptr;
53 casadi_dcopy_t casadi_dcopy_hook =
nullptr;
56 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
57 std::mutex Blas::mutex_solvers_;
63 casadi_int m, casadi_int n, casadi_int k,
65 const double* A, casadi_int lda,
66 const double* B, casadi_int ldb,
68 double* C, casadi_int ldc) {
77 const casadi_int lda_canonical = transa_yes ? k : m;
78 const bool canonical = !transb_yes
79 && alpha == 1.0 && beta == 1.0
80 && lda == lda_canonical && ldb == k && ldc == m;
85 casadi_mtimes_dense<double>(A, k, m, B, n,
C, 1);
88 casadi_mtimes_dense<double>(A, m, k, B, n,
C, 0);
95 for (casadi_int j = 0; j < n; ++j) {
96 double* col =
C + j * ldc;
97 for (casadi_int i = 0; i < m; ++i) col[i] = 0.0;
99 }
else if (beta != 1.0) {
100 for (casadi_int j = 0; j < n; ++j) {
101 double* col =
C + j * ldc;
102 for (casadi_int i = 0; i < m; ++i) col[i] *= beta;
106 for (casadi_int j = 0; j < n; ++j) {
107 for (casadi_int l = 0; l < k; ++l) {
108 const double b_lj = transb_yes ? B[j + l * ldb] : B[l + j * ldb];
109 if (b_lj == 0.0)
continue;
110 const double scl = alpha * b_lj;
111 double* col =
C + j * ldc;
113 const double* a_col = A + l;
115 for (casadi_int i = 0; i < m; ++i) col[i] += scl * a_col[i * lda];
117 const double* a_col = A + l * lda;
118 for (casadi_int i = 0; i < m; ++i) col[i] += scl * a_col[i];
128 "Built-in dense BLAS implementation, no external dependency. "
129 "Used by default and as the fallback when other plugins are unavailable.";
131 #ifdef CASADI_CORE_BLAS_DEPENDENCY
133 #ifdef CASADI_L1_BLAS
134 extern "C" void casadi_blas_classic_set_l1_hooks();
136 const bool _casadi_core_l1 = (casadi_blas_classic_set_l1_hooks(),
true);
142 #ifdef CASADI_CORE_BLAS_DEPENDENCY
143 static bool core_blas_inited =
false;
144 if (!core_blas_inited) {
145 core_blas_inited =
true;
147 setDefault(
"classic");
150 if (name ==
"reference")
return 0;
151 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
152 std::lock_guard<std::mutex> lock(Blas::mutex_solvers_);
165 casadi_assert_dev(it !=
solvers_.end());
170 const Plugin* p = &it->second;
171 for (casadi_int sh = 1; sh < static_cast<casadi_int>(
dispatch_.size()); ++sh) {
177 return static_cast<casadi_int
>(
dispatch_.size() - 1);
181 int transa,
int transb,
182 casadi_int m, casadi_int n, casadi_int k,
184 const double* A, casadi_int lda,
185 const double* B, casadi_int ldb,
187 double* C, casadi_int ldc) {
188 if (shorthand == 0) {
190 reference_dgemm(transa, transb, m, n, k, alpha, A, lda, B, ldb, beta,
C, ldc);
195 casadi_assert_dev(shorthand <
static_cast<casadi_int
>(
dispatch_.size()));
196 casadi_assert_dev(
dispatch_[shorthand] !=
nullptr);
198 transa, transb, m, n, k, alpha, A, lda, B, ldb, beta,
C, ldc);
202 const double* A, casadi_int m, casadi_int k,
203 const double* B, casadi_int n,
205 if (shorthand == 0) {
208 casadi_mtimes_dense<double>(A, m, k, B, n,
C, 0);
213 casadi_assert_dev(shorthand <
static_cast<casadi_int
>(
dispatch_.size()));
214 casadi_assert_dev(
dispatch_[shorthand] !=
nullptr);
217 m, n, k, 1.0, A, m, B, k, 1.0,
C, m);
221 if (shorthand == 0)
return "reference";
224 casadi_assert_dev(shorthand <
static_cast<casadi_int
>(
dispatch_.size()));
225 casadi_assert_dev(
dispatch_[shorthand] !=
nullptr);
230 const std::string& A,
231 casadi_int m, casadi_int k,
232 const std::string& B, casadi_int n,
233 const std::string& C) {
234 if (shorthand == 0) {
236 g << g.
mtimes(A, m, k, B, n,
C,
false) <<
'\n';
242 casadi_assert_dev(shorthand <
static_cast<casadi_int
>(
dispatch_.size()));
243 casadi_assert_dev(
dispatch_[shorthand] !=
nullptr);
245 casadi_assert(p->exposed.codegen_mtimes !=
nullptr,
246 "BLAS plugin '" + std::string(p->name) +
"' does not implement codegen.");
247 p->exposed.codegen_mtimes(g, A, m, k, B, n,
C);
251 if (name ==
"reference")
return true;
256 if (name ==
"reference")
return;
265 void Blas::setDefault(
const std::string& name) {
267 #ifdef CASADI_L1_BLAS
270 casadi_daxpy_hook = e ? e->daxpy :
nullptr;
271 casadi_ddot_hook = e ? e->ddot :
nullptr;
272 casadi_dscal_hook = e ? e->dscal :
nullptr;
273 casadi_dnrm2_hook = e ? e->dnrm2 :
nullptr;
274 casadi_dasum_hook = e ? e->dasum :
nullptr;
275 casadi_dcopy_hook = e ? e->dcopy :
nullptr;
284 const std::vector<std::string>& inst) {
287 "// SYMBOL \"copy\"\n"
288 "void casadi_copy(const casadi_real* x, casadi_int n, casadi_real* y) {\n"
290 " if (x) memcpy(y, x, n*sizeof(casadi_real));\n"
291 " else memset(y, 0, n*sizeof(casadi_real));\n"
297 const std::vector<std::string>& inst) {
300 if (!fn)
return false;
306 const std::vector<std::string>& inst) {
309 if (!fn)
return false;
315 const std::vector<std::string>& inst) {
318 if (!fn)
return false;
324 const std::vector<std::string>& inst) {
327 if (!fn)
return false;
333 const std::vector<std::string>& inst) {
336 if (!fn)
return false;
static bool codegen_dot_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static bool codegen_norm_1_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static const std::string infix_
static casadi_int default_
static std::string getDefault()
void(* CodegenL1Aux)(CodeGenerator &g, const std::vector< std::string > &inst)
static void codegen_copy_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static void mtimes(casadi_int shorthand, const double *A, casadi_int m, casadi_int k, const double *B, casadi_int n, double *C)
static bool codegen_scal_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static std::map< std::string, Plugin > solvers_
static bool codegen_axpy_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static bool codegen_norm_2_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static std::vector< const Plugin * > dispatch_
static const char * name_for_shorthand(casadi_int shorthand)
static void reference_dgemm(int transa, int transb, casadi_int m, casadi_int n, casadi_int k, double alpha, const double *A, casadi_int lda, const double *B, casadi_int ldb, double beta, double *C, casadi_int ldc)
static casadi_int shorthand_for(const std::string &name)
static void codegen_mtimes(CodeGenerator &g, casadi_int shorthand, const std::string &A, casadi_int m, casadi_int k, const std::string &B, casadi_int n, const std::string &C)
static void dgemm(casadi_int shorthand, int transa, int transb, casadi_int m, casadi_int n, casadi_int k, double alpha, const double *A, casadi_int lda, const double *B, casadi_int ldb, double beta, double *C, casadi_int ldc)
Helper class for C code generation.
std::string mtimes(const std::string &x, const Sparsity &sp_x, const std::string &y, const Sparsity &sp_y, const std::string &z, const Sparsity &sp_z, const std::string &w, bool tr)
Codegen sparse matrix-matrix multiplication.
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
std::stringstream auxiliaries
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.
void CASADI_BLAS_CLASSIC_EXPORT casadi_load_blas_classic()
bool has_blas(const std::string &name)
std::string doc_blas(const std::string &name)
void load_blas(const std::string &name)
static const char * REFERENCE_DOC