typename viennacl::enable_if< viennacl::is_any_sparse_matrix<SparseMatrixType>::value>::type prod_impl(const SparseMatrixType & sp_mat, const viennacl::matrix_base<ScalarType> & d_mat, viennacl::matrix_base<ScalarType> & result) { assert( (sp_mat.size1() == result.size1()) && bool("Size check failed for compressed matrix - dense matrix product: size1(sp_mat) != size1(result)")); assert( (sp_mat.size2() == d_mat.size1()) && bool("Size check failed for compressed matrix - dense matrix product: size2(sp_mat) != size1(d_mat)")); switch (viennacl::traits::handle(sp_mat).get_active_handle_id()) { case viennacl::MAIN_MEMORY: viennacl::linalg::host_based::prod_impl(sp_mat, d_mat, result); break; #ifdef VIENNACL_WITH_OPENCL case viennacl::OPENCL_MEMORY: viennacl::linalg::opencl::prod_impl(sp_mat, d_mat, result); break; #endif #ifdef VIENNACL_WITH_CUDA case viennacl::CUDA_MEMORY: viennacl::linalg::cuda::prod_impl(sp_mat, d_mat, result); break; #endif case viennacl::MEMORY_NOT_INITIALIZED: throw memory_exception("not initialised!"); default: throw memory_exception("not implemented"); } }
typename viennacl::enable_if< viennacl::is_any_sparse_matrix<SparseMatrixType>::value>::type assign_to_dense(SparseMatrixType const & A, viennacl::matrix_base<NumericT> & B) { assert( (A.size1() == B.size1()) && bool("Size check failed for assignment to dense matrix: size1(A) != size1(B)")); assert( (A.size2() == B.size1()) && bool("Size check failed for assignment to dense matrix: size2(A) != size2(B)")); switch (viennacl::traits::handle(A).get_active_handle_id()) { case viennacl::MAIN_MEMORY: viennacl::linalg::host_based::amg::assign_to_dense(A, B); break; #ifdef VIENNACL_WITH_OPENCL case viennacl::OPENCL_MEMORY: viennacl::linalg::opencl::amg::assign_to_dense(A, B); break; #endif #ifdef VIENNACL_WITH_CUDA case viennacl::CUDA_MEMORY: viennacl::linalg::cuda::amg::assign_to_dense(A, B); break; #endif case viennacl::MEMORY_NOT_INITIALIZED: throw memory_exception("not initialised!"); default: throw memory_exception("not implemented"); } }
void nmf(viennacl::matrix_base<ScalarType> const & V, viennacl::matrix_base<ScalarType> & W, viennacl::matrix_base<ScalarType> & H, viennacl::linalg::nmf_config const & conf) { assert(V.size1() == W.size1() && V.size2() == H.size2() && bool("Dimensions of W and H don't allow for V = W * H")); assert(W.size2() == H.size1() && bool("Dimensions of W and H don't match, prod(W, H) impossible")); switch (viennacl::traits::handle(V).get_active_handle_id()) { case viennacl::MAIN_MEMORY: viennacl::linalg::host_based::nmf(V, W, H, conf); break; #ifdef VIENNACL_WITH_OPENCL case viennacl::OPENCL_MEMORY: viennacl::linalg::opencl::nmf(V,W,H,conf); break; #endif #ifdef VIENNACL_WITH_CUDA case viennacl::CUDA_MEMORY: viennacl::linalg::cuda::nmf(V,W,H,conf); break; #endif case viennacl::MEMORY_NOT_INITIALIZED: throw memory_exception("not initialised!"); default: throw memory_exception("not implemented"); } }
void nmf(viennacl::matrix_base<NumericT> const & V, viennacl::matrix_base<NumericT> & W, viennacl::matrix_base<NumericT> & H, viennacl::linalg::nmf_config const & conf) { viennacl::hsa::context & ctx = const_cast<viennacl::hsa::context &>(viennacl::traits::hsa_context(V)); const std::string NMF_MUL_DIV_KERNEL = "el_wise_mul_div"; viennacl::linalg::opencl::kernels::nmf<NumericT, viennacl::hsa::context>::init(ctx); vcl_size_t k = W.size2(); conf.iters_ = 0; if (viennacl::linalg::norm_frobenius(W) <= 0) W = viennacl::scalar_matrix<NumericT>(W.size1(), W.size2(), NumericT(1), ctx); if (viennacl::linalg::norm_frobenius(H) <= 0) H = viennacl::scalar_matrix<NumericT>(H.size1(), H.size2(), NumericT(1), ctx); viennacl::matrix_base<NumericT> wn(V.size1(), k, W.row_major(), ctx); viennacl::matrix_base<NumericT> wd(V.size1(), k, W.row_major(), ctx); viennacl::matrix_base<NumericT> wtmp(V.size1(), V.size2(), W.row_major(), ctx); viennacl::matrix_base<NumericT> hn(k, V.size2(), H.row_major(), ctx); viennacl::matrix_base<NumericT> hd(k, V.size2(), H.row_major(), ctx); viennacl::matrix_base<NumericT> htmp(k, k, H.row_major(), ctx); viennacl::matrix_base<NumericT> appr(V.size1(), V.size2(), V.row_major(), ctx); NumericT last_diff = 0; NumericT diff_init = 0; bool stagnation_flag = false; for (vcl_size_t i = 0; i < conf.max_iterations(); i++) { conf.iters_ = i + 1; { hn = viennacl::linalg::prod(trans(W), V); htmp = viennacl::linalg::prod(trans(W), W); hd = viennacl::linalg::prod(htmp, H); viennacl::hsa::kernel & mul_div_kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::nmf<NumericT>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::hsa::enqueue(mul_div_kernel(H, hn, hd, cl_uint(H.internal_size1() * H.internal_size2()))); } { wn = viennacl::linalg::prod(V, trans(H)); wtmp = viennacl::linalg::prod(W, H); wd = viennacl::linalg::prod(wtmp, trans(H)); viennacl::hsa::kernel & mul_div_kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::nmf<NumericT>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::hsa::enqueue(mul_div_kernel(W, wn, wd, cl_uint(W.internal_size1() * W.internal_size2()))); } if (i % conf.check_after_steps() == 0) //check for convergence { appr = viennacl::linalg::prod(W, H); appr -= V; NumericT diff_val = viennacl::linalg::norm_frobenius(appr); if (i == 0) diff_init = diff_val; if (conf.print_relative_error()) std::cout << diff_val / diff_init << std::endl; // Approximation check if (diff_val / diff_init < conf.tolerance()) break; // Stagnation check if (std::fabs(diff_val - last_diff) / (diff_val * NumericT(conf.check_after_steps())) < conf.stagnation_tolerance()) //avoid situations where convergence stagnates { if (stagnation_flag) // iteration stagnates (two iterates with no notable progress) break; else // record stagnation in this iteration stagnation_flag = true; } else // good progress in this iteration, so unset stagnation flag stagnation_flag = false; // prepare for next iterate: last_diff = diff_val; } } }
static vcl_size_t size2(viennacl::matrix_base<T> const & lhs, ScalarType const & /*rhs*/) { return lhs.size2(); }
static vcl_size_t size1(viennacl::matrix_base<ScalarType> const & lhs, viennacl::matrix_expression<T2, T2, op_trans> const & /*rhs*/) { return lhs.size1(); }
static vcl_size_t size2(viennacl::matrix_expression<T1, T1, op_trans> const & /*lhs*/, viennacl::matrix_base<ScalarType> const & rhs) { return rhs.size2(); }
static std::size_t size1(viennacl::matrix_base<T, F> const & lhs, ScalarType const & /*rhs*/) { return lhs.size1(); }
static vcl_size_t size2(ScalarType const & /*lhs*/, viennacl::matrix_base<ScalarType> const & rhs) { return rhs.size2(); }