Hi, first of all thanks for all your work.
I have a question regarding within-chain parallelisation using the function reduce_sum because I see a really strange behaviour, as the model with parallelisation is much slower than the model without it using cmdstanr.
My model is a liability threshold model which aim to estimate at variance components using individuals clustered in families. Liabilities are simulated from a truncated multivariate normal distribution, therefore each individual has an underlying liability distribution which slow the program. The likelihood is calculated summing the contribution of each family and not each individuals. Anyway, model works fine, but I wanted to improve speed through within-chain parallelisation (in case of large sample size and to perform simulations), summing the partial sum from each family, but I donāt know why I get the opposite result. I post the code, do you have any idea for this behaviour?
// log-likelihood based on a truncated multivariate normal distribution.
// families are sliced so that the computation is parellilised.
functions {
real partial_sum(int[] fam_slice,
int start, int end,
vector X, matrix Sigma, int[] ni, int[] firstfam, vector lb, vector ub, vector lb_ind, vector ub_ind, vector u, int NFAM, int minff, int maxff,int minni, int maxni) {
real likelihood = 0;
// loop needed to extract data for the specific family and needed to compute the likelihood
for (k in start:end) {
int nik=ni[k];
int firstfamk =firstfam[k];
matrix [nik,nik] Sigmakc=cholesky_decompose(block(Sigma, firstfamk, firstfamk, nik, nik));
vector[nik] Xk=segment(X, firstfamk ,nik);
vector[nik] lbk=segment(lb, firstfamk ,nik);
vector[nik] ubk=segment(ub, firstfamk ,nik);
vector[nik] lb_indk=segment(lb_ind, firstfamk ,nik);
vector[nik] ub_indk=segment(ub_ind, firstfamk ,nik);
vector[nik] uk=segment(u, firstfamk ,nik);
// likelihood computation
int M = rows(uk);
vector[M] z;
real prob = 0;
for ( m in 1:M ) {
if ( lb_indk[m] == 0 && ub_indk[m] == 0 ) z[m] = inv_Phi(uk[m]);
else {
int km1 = m - 1;
real v;
real z_star;
real logd;
row_vector [2] log_ustar = [negative_infinity(), 0];
real constrain = Xk[m] + ((m > 1) ? Sigmakc[m, 1:km1] * head(z, km1) : 0);
if ( lb_indk[m] == 1 ) log_ustar[1] = normal_lcdf( ( lbk[m] - constrain ) / Sigmakc[m, m] | 0.0, 1.0 );
if ( ub_indk[m] == 1 ) log_ustar[2] = normal_lcdf( ( ubk[m] - constrain ) / Sigmakc[m, m] | 0.0, 1.0 );
logd = log_diff_exp(log_ustar[2], log_ustar[1]);
v = exp( log_sum_exp( log_ustar[1], log(uk[m]) + logd ) );
z[m] = inv_Phi(v);
prob += logd;
}
}
likelihood += prob;
}
return likelihood ; // likelihood
}
}
..... // data omitted
// parameters: variance components and individual uniformn distributio needed to compute liabilities
parameters {
real<lower=0,upper=1> heritability;
real<lower=0,upper=1-heritability> sharedenvironment;
vector<lower=0,upper=1>[N] u;
}
model {
matrix[N, N] Sigma;
Sigma = (heritability*pedigree_matrix + sharedenvironment*household_matrix + (1-heritability-sharedenvironment)*identity_matrix);
target += reduce_sum(partial_sum, fam, grainsize, X, Sigma, ni, firstfam, lb, ub, lb_ind, ub_ind, u, NFAM, minff, maxff,minni, maxni);
heritability~ beta(12,12);
sharedenvironment~ beta(6,14) ;
}
****
Thanks for any help
Andrea