GP Regression Example with Stan on GPU

I’ve recently compiled cmdstan with gpu support, and I thought I’d try running the example models from Cesnovar et al. (https://arxiv.org/abs/1907.01063) to make sure everything is working properly. I was able to compile and fit the Bernoulli GLM model from the paper without a problem, and the stan output confirmed that it was running with opencl support enabled. However, I’ve run into a problem trying to get the GP regression example working. Here’s the code for their model:

functions {
  vector gp_pred_rng(real[] x2,
                     vector y1, real[] x1,
                     real alpha, real rho, real sigma, real delta) {
    int N1 = rows(y1);
    int N2 = size(x2);
    vector[N2] f2;
    {
      matrix[N1, N1] K =   cov_exp_quad(x1, alpha, rho)
                         + diag_matrix(rep_vector(square(sigma), N1));
      matrix[N1, N1] L_K = cholesky_decompose(K);

      vector[N1] L_K_div_y1 = mdivide_left_tri_low(L_K, y1);
      vector[N1] K_div_y1 = mdivide_right_tri_low(L_K_div_y1', L_K)';
      matrix[N1, N2] k_x1_x2 = cov_exp_quad(x1, x2, alpha, rho);
      vector[N2] f2_mu = (k_x1_x2' * K_div_y1);
      matrix[N1, N2] v_pred = mdivide_left_tri_low(L_K, k_x1_x2);
      matrix[N2, N2] cov_f2 =   cov_exp_quad(x2, alpha, rho) - v_pred' * v_pred
                              + diag_matrix(rep_vector(delta, N2));
      f2 = multi_normal_rng(f2_mu, cov_f2);
    }
    return f2;
  }
}

data {
  int<lower=1> N;
  real x[N];
  vector[N] y;

  int<lower=1> N_predict;
  real x_predict[N_predict];
}

parameters {
  real<lower=0> rho;
  real<lower=0> alpha;
  real<lower=0> sigma;
}

model {
  matrix[N, N] cov =   cov_exp_quad(x, alpha, rho)
                     + diag_matrix(rep_vector(square(sigma), N));
  matrix[N, N] L_cov = cholesky_decompose(cov);

  rho ~ inv_gamma(8.91924, 34.5805);
  alpha ~ normal(0, 2);
  sigma ~ normal(0, 1);

  y ~ multi_normal_cholesky(rep_vector(0, N), L_cov);
}

generated quantities {
  vector[N_predict] f_predict = gp_pred_rng(x_predict, y, x, alpha, rho, sigma, 1e-10);
  vector[N_predict] y_predict;
  for (n in 1:N_predict)
    y_predict[n] = normal_rng(f_predict[n], sigma);
}

When I try to compile the stan file with cmdstan, I get the following error:

--- Compiling, linking C++ code ---
g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare   -I stan/lib/stan_math/lib/opencl_2.2.0   -I stan/lib/stan_math/lib/tbb_2019_U8/include -O3 -I src -I stan/src -I lib/rapidjson_1.1.0/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.3 -I stan/lib/stan_math/lib/boost_1.72.0 -I stan/lib/stan_math/lib/sundials_5.1.0/include    -DBOOST_DISABLE_ASSERTS  -DSTAN_OPENCL -DOPENCL_DEVICE_ID=0 -DOPENCL_PLATFORM_ID=0 -DCL_HPP_TARGET_OPENCL_VERSION=120 -DCL_HPP_MINIMUM_OPENCL_VERSION=120 -DCL_HPP_ENABLE_EXCEPTIONS -Wno-ignored-attributes    -c  -x c++ -o /home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.o /home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp: In instantiation of ‘void GP_model_namespace::GP_model::write_array(RNG&, std::vector<double>&, std::vector<int>&, std::vector<double>&, bool, bool, std::ostream*) const [with RNG = boost::random::additive_combine_engine<boost::random::linear_congruential_engine<unsigned int, 40014, 0, 2147483563>, boost::random::linear_congruential_engine<unsigned int, 40692, 0, 2147483399> >; std::ostream = std::basic_ostream<char>]’:
stan/src/stan/model/model_base_crtp.hpp:200:70:   required from ‘void stan::model::model_base_crtp<M>::write_array(boost::random::ecuyer1988&, std::vector<double>&, std::vector<int>&, std::vector<double>&, bool, bool, std::ostream*) const [with M = GP_model_namespace::GP_model; boost::random::ecuyer1988 = boost::random::additive_combine_engine<boost::random::linear_congruential_engine<unsigned int, 40014, 0, 2147483563>, boost::random::linear_congruential_engine<unsigned int, 40692, 0, 2147483399> >; std::ostream = std::basic_ostream<char>]’
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp:823:1:   required from here
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp:610:20: error: no matching function for call to ‘gp_pred_rng(const std::vector<double>&, const Eigen::Matrix<double, -1, 1>&, const std::vector<double>&, double&, double&, double&, double, boost::random::additive_combine_engine<boost::random::linear_congruential_engine<unsigned int, 40014, 0, 2147483563>, boost::random::linear_congruential_engine<unsigned int, 40692, 0, 2147483399> >&, std::ostream*&)’
     gp_pred_rng(x_predict, y, x, alpha, rho, sigma,
     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       1e-10, base_rng__, pstream__), "assigning variable f_predict");
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp:131:1: note: candidate: template<class RNG, class T0__, class T1__, class T2__, class T3__, class T4__, class T5__, class T6__> Eigen::Matrix<typename boost::math::tools::promote_args<T0__, T1__, T2__, T3__, T4__, typename boost::math::tools::promote_args<T5__, T6__>::type>::type, -1, 1> GP_model_namespace::gp_pred_rng(RNG&, const std::vector<T2>&, const Eigen::Matrix<T, -1, 1, 0, -1, 1>&, const std::vector<T_l>&, const T3__&, const T4__&, const T5__&, const T6__&, std::ostream*)
 gp_pred_rng(RNG& base_rng__, const std::vector<T0__>& x2,
 ^~~~~~~~~~~
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp:131:1: note:   template argument deduction/substitution failed:
/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP.hpp:610:20: note:   ‘const Eigen::Matrix<double, -1, 1>’ is not derived from ‘const std::vector<T2>’
     gp_pred_rng(x_predict, y, x, alpha, rho, sigma,
     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       1e-10, base_rng__, pstream__), "assigning variable f_predict");
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make/program:42: recipe for target '/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP' failed
make: *** [/home/collin/gpu-stan-paper-materials/replicationScripts/endToEnd/gp_regression/Stan/GP] Error 1

I can see that the problem lies somewhere with the custom function for generating draws from the posterior predictive distribution. When I tried removing that and the generated quantities block, the model compiled and ran without a problem. Furthermore, when I try compiling the above model (including the custom function) from rstan (installed on a separate computer from the standard repo without gpu support), the compilation also finishes successfully.

Other than that though, I’m not sure how to tell whether the problem is with my installation of stanc, something in the math library, or something else. My installation is running on Ubuntu 18.04, my gpu is an AMD Radeon 5700XT, and I’m using AMD’s proprietary opencl drivers. Thanks for any insight you can provide!

Hi Collin,

this error is not related to any of the GPU features. This one is related to the new Stan-to-C++ compiler we are using in Cmdstan 2.22.
The issue you are facing was already spotted (https://github.com/stan-dev/stanc3/issues/460) and also squashed about and hour ago (https://github.com/stan-dev/stanc3/pull/461).

You can obtain it by running the following in the Cmdstan folder:

rm bin/stanc bin/linux-stanc bin/mac-stanc
make build

This will download the bugfixed version of the Stan-to-C++ compiler.

2 Likes