Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Eigen Type traits #1667

Closed
wants to merge 25 commits into from
Closed

Conversation

SteveBronder
Copy link
Collaborator

@SteveBronder SteveBronder commented Feb 2, 2020

Summary

Cleans up and expands the type traits for selecting certain Eigen types. This uses Eigen's inheritance structure to determine for each type trait whether the type we are checking inherits a particular Eigen base class. In order, the hierarchy for types is essentially

  • EigenBase
    • DenseBase
      • MatrixBase
        • Matrix
      • ArrayBase
        • Array
      • MapBase
      • LDLT
      • LLT
    • SparseMatrixBase
      • SparseCompressedMatrixBase
        • SparseMatrix

This PR includes functions to check types that inherit from EigenBase, DenseBase, MatrixBase, ArrayBase, MapBase, and SparseMatrixBase.

This PR also changes the definition of is_eigen_matrix to be anything that inherits from Eigen::MatrixBase with more than one row and column. There were places where we want to specialize for eigen vectors while having other specialization for general eigen matrices. This meant we had to do something like

template <typename EigMat, typename = require_eigen_t<EigMat>,
  typename = require_not_eigen_vector_t<EigMat>>

Which is annoying. With this PR we can just write

template <typename EigMat, typename = require_eigen_matrix_t<EigMat>>

Tests

Tests are done for generic eigen expressions inheriting from each type above and for all stan scalar types. They can be run with

./runTests.py ./test/unit/math/mix/meta/ -f eigen

Side Effects

Yes, the definition of is_eigen_matrix will now accept more generic eigen expressions.

Checklist

  • Math issue Update internals to use more modern c++ #1308

  • Copyright holder: Steve Bronder

    The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
    - Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
    - Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

  • the basic tests are passing

    • unit tests pass (to run, use: ./runTests.py test/unit)
    • header checks pass, (make test-headers)
    • dependencies checks pass, (make test-math-dependencies)
    • docs build, (make doxygen)
    • code passes the built in C++ standards checks (make cpplint)
  • the code is written in idiomatic C++ and changes are documented in the doxygen

  • the new changes are tested

@syclik
Copy link
Member

syclik commented Feb 3, 2020

Conceptually, wouldn’t it be better if we called this is_eigen_dense or even something more verbose like is_eigen_densebase? That would allow us to specialize for Eigen::Matrix if we ever needed to. And if we don’t, at least it’s clear that we don’t actually mean Eigen::Matrix.

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 4.82 4.91 0.98 -1.91% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 0.97 -2.61% slower
eight_schools/eight_schools.stan 0.09 0.09 0.98 -2.0% slower
gp_regr/gp_regr.stan 0.22 0.22 1.0 0.05% faster
irt_2pl/irt_2pl.stan 6.05 6.06 1.0 -0.19% slower
performance.compilation 89.57 87.19 1.03 2.66% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.33 7.3 1.0 0.32% faster
pkpd/one_comp_mm_elim_abs.stan 22.13 20.98 1.05 5.2% faster
sir/sir.stan 91.93 91.52 1.0 0.45% faster
gp_regr/gen_gp_data.stan 0.05 0.05 0.99 -0.81% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.98 3.01 0.99 -1.05% slower
pkpd/sim_one_comp_mm_elim_abs.stan 0.32 0.31 1.01 1.08% faster
arK/arK.stan 1.76 1.76 1.0 -0.18% slower
arma/arma.stan 0.8 0.8 0.99 -0.56% slower
garch/garch.stan 0.59 0.58 1.01 1.01% faster
Mean result: 1.00132900475

Jenkins Console Log
Blue Ocean
Commit hash: b1fa492


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@SteveBronder
Copy link
Collaborator Author

Conceptually, wouldn’t it be better if we called this is_eigen_dense or even something more verbose like is_eigen_densebase? That would allow us to specialize for Eigen::Matrix if we ever needed to. And if we don’t, at least it’s clear that we don’t actually mean Eigen::Matrix.

What if we just switched it to Eigen::MatrixBase? That type has all the attributes of an Eigen matrix. My only concern is that there are functions in Eigen that return DenseBaseCoeff classes, I'm not sure if those would be caught if we look for just things that inherit from MatrixBase.

I think with the direction things are going we wouldn't want an explicit specialization for Eigen::Matrix. imo it's about deciding whether a DenseBase is conceptually enough to say, "This is matrix-ish"

@t4c1 ?

@t4c1
Copy link
Contributor

t4c1 commented Feb 3, 2020

I agree with @syclik. I would prefere to keep the name is_eigen_matrix free in case we ever need it to distinguish between Eigen Matrix and Array. I would propose to name the thing you are trying to do here is_eigen_and_not_vector or something similar.

What if we just switched it to Eigen::MatrixBase?

What exactley do you mean by switch to it?

@bob-carpenter
Copy link
Contributor

bob-carpenter commented Feb 3, 2020 via email

@t4c1
Copy link
Contributor

t4c1 commented Feb 3, 2020

It will also match any expression that evaluates to Matrix<T, -1, -1>. Hierarchy of Eigen classes should help determining how things can be matched: https://eigen.tuxfamily.org/dox/TopicClassHierarchy.html

@bob-carpenter
Copy link
Contributor

bob-carpenter commented Feb 3, 2020 via email

@SteveBronder
Copy link
Collaborator Author

I agree with @syclik. I would prefer to keep the name is_eigen_matrix free in case we ever need it to distinguish between Eigen Matrix and Array. I would propose to name the thing you are trying to do here is_eigen_and_not_vector or something similar.

idk if I like having the concept be named by what it's not. I have to think about that. How about is_eigen_dense_matrix? I can clean up the definition here to be

" is_eigen_dense_matrix will hold a static bool defined as true if the template parameter T both inherits from Eigen::DenseBase and neither the compile time number of rows and columns is 1"

So the above fits for dynamic Eigen matrices and fixed size matrices. Does that conceptually/practically seem clear enough? Though it leaves a Eigen::Matrix<double, 1, 1> as not a matrix (a row and column vector I guess?) I'm not sure how I feel about that.

What if we just switched it to Eigen::MatrixBase?

What exactly do you mean by switch to it?

Jus switching the above definition to say Eigen::MatrixBase

How about is_eigen_matrix_assignable instead or is_assignable_eigen_matrix to keep our naming in line with std::is_assignable?

Are there other places we use std::is_assignable?

Or given that we don't have other types of matrices, we could just drop the "eigen" here.

matrix_cl<>!

@bob-carpenter
Copy link
Contributor

@SteveBronder : I think our suggestions crossed in the ether. I prefer is_eigen_matrix_assignable or is_assignable_eigen_matrix (or without the eigen_) to follow std::is_assignable. And that's what we're talking about here---assignability. That's what an eval() does.

@t4c1
Copy link
Contributor

t4c1 commented Feb 3, 2020

idk if I like having the concept be named by what it's not.

I think that is the only way not to be ambiguous. The problem is that row and column vectors are special cases of matrices and I don't think we have a word for a matrix that is not a vector.

Calling it either is_eigen_matrix, is_dense_matrix or is_matrix_assignable does not convey that vectors are not accepted.

@bob-carpenter
Copy link
Contributor

bob-carpenter commented Feb 3, 2020

Despite the superficial similarity, there are three distinct overloads of Matrix<T, R, C> that we use. Given how C++ works, the only relation among these classes is that they all overload the base template class. Each has its own distinct implementation and produces different return types for operators like operator*. I suggest we settle on the terminology:

  • matrix: Matrix<T, -1, -1>
  • column vector: Matrix<T, -1, 1>
  • row vector: Matrix<T, 1, -1>

We can use "vector" for either row or column vectors, though in informal math writing, when we say "vector" we usually mean column vectors.

@t4c1
Copy link
Contributor

t4c1 commented Feb 3, 2020

If we use suggested terminology the term "matrix" becomes ambiguous. It could mean any matrix or just Matrix<T,-1,-1>.

@bob-carpenter
Copy link
Contributor

bob-carpenter commented Feb 3, 2020 via email

@SteveBronder
Copy link
Collaborator Author

If we use suggested terminology the term "matrix" becomes ambiguous. It could mean any matrix or just Matrix<T,-1,-1>.

I think there's two points to call here

  1. it matters whether you consider whether a row/col vector is also a matrix. In math row/col vectors are certainly matrices, but when doing code stuff it feels like we handle them pretty differently. Hence the definition/PR.
  2. The definition I give below explicitly allows for fixed matrices like Eigen::Matrix<double, 10, 10>. At this time we don't use those (Unless a computation gives back a [1, 1], but with the new compiler if a user tells us the size of a vector/matrix during compile time we could use fixed matrices and do much fewer dynamic allocations

how would you want to correct the below definition? Or is it just the name?

" is_eigen_dense_matrix will hold a static bool defined as true if the template parameter T both inherits from Eigen::DenseBase and neither the compile time number of rows and or columns is 1"

ftr I'm thinking along Bob's line in the below where computationally we treat vectors different conceptually in the codebase

Despite the superficial similarity, there are three distinct overloads of Matrix<T, R, C> that we use. Given how C++ works, the only relation among these classes is that they all overload the base template class. Each has its own distinct implementation and produces different return types for operators like operator*. I suggest we settle on the terminology:

  • matrix: Matrix<T, -1, -1>
  • column vector: Matrix<T, -1, 1>
  • row vector: `Matrix<T, 1, -1>
    We can use "vector" for either row or column vectors, though in informal math writing, when we say "vector" we usually mean column vectors.

@bob-carpenter
Copy link
Contributor

bob-carpenter commented Feb 3, 2020

In math row/col vectors are certainly matrices, but when doing code stuff it feels like we handle them pretty differently.

Exactly. It's like the relation between integers and real numbers, or between reals and complex.

but with the new compiler if a user tells us the size of a vector/matrix during compile time we could use fixed matrices and do much fewer dynamic allocations

This is tricky. Eigen itself only recommends doing this for very small matrices (single digit sizes) because everything would otherwise be allocated on the stack, which is of very limited size, especially with multithreading (on the order of 20KB, so anything beyond about 50 x 50 is going to blow out stack memory).

how would you want to correct the below definition?

is_eigen_matrix_assignable<T>::value is true if the type T is assignable to type Eigen::Matrix<U, -1, -1>, where U is the scalar type of T.

This explicitly doesn't consider Matrix<U, 2, 2>, nor do I think we should be using the fixed size types. But, if that becomes necessary, I'd amend the definition to:

is_eigen_matrix_assignable<T>::value is true if either (a) the type T is assignable to type Eigen::Matrix<U, -1, -1>, or (b) if the type T is assignable to type Eigen::Matrix<U, R, C> with R and C both strictly greater than 1. In both cases, U is the underlying scalar type of T.

@SteveBronder
Copy link
Collaborator Author

SteveBronder commented Feb 8, 2020

Mulling this over I like this definition

is_eigen_matrix_assignable::value is true if the type T is assignable to type Eigen::Matrix<U, -1, -1>, where U is the scalar type of T.

Though I changed it slightly to be just

Checks whether type T is derived from Eigen::MatrixBase and has columns and rows not equal to 1.

imo I think this makes sense because this is the base class for eigen matrices. See below for Eigen's reference on that

https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 4.96 4.93 1.01 0.63% faster
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 1.01 0.71% faster
eight_schools/eight_schools.stan 0.1 0.09 1.06 5.97% faster
gp_regr/gp_regr.stan 0.22 0.22 1.0 0.47% faster
irt_2pl/irt_2pl.stan 6.06 6.15 0.99 -1.44% slower
performance.compilation 88.03 87.31 1.01 0.82% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.49 7.49 1.0 -0.05% slower
pkpd/one_comp_mm_elim_abs.stan 21.26 21.37 0.99 -0.51% slower
sir/sir.stan 91.96 89.99 1.02 2.14% faster
gp_regr/gen_gp_data.stan 0.05 0.05 0.99 -1.34% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.99 3.0 1.0 -0.15% slower
pkpd/sim_one_comp_mm_elim_abs.stan 0.32 0.33 0.97 -2.64% slower
arK/arK.stan 1.75 1.75 1.0 0.37% faster
arma/arma.stan 0.8 0.79 1.0 0.38% faster
garch/garch.stan 0.59 0.58 1.0 0.16% faster
Mean result: 1.00405490583

Jenkins Console Log
Blue Ocean
Commit hash: 7aae65d


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@SteveBronder
Copy link
Collaborator Author

This is ready for review

Copy link
Contributor

@bob-carpenter bob-carpenter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More doc and testing please. Also, I'd like to hear from @syclik about conventions for splitting functions across files.

stan/math/prim/meta/is_eigen.hpp Outdated Show resolved Hide resolved
stan/math/prim/meta/is_eigen.hpp Outdated Show resolved Hide resolved
@@ -102,6 +102,13 @@ template <template <class...> class TypeCheck, class... Check>
struct is_eigen_value_check
: container_value_type_check_base<is_eigen, TypeCheck, Check...> {};

/**
* Meta type trait to check if type inherits from EigenBase.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should have their template parameters documented as well as what kind of value they're going to produce. Same for all the rest of these traits classes.

stan/math/prim/meta/require_generics.hpp Outdated Show resolved Hide resolved
@@ -799,6 +834,30 @@ template <template <class...> class TypeCheck, class... Check>
using require_all_not_eigen_vt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really needs doc because I have no idea what the v is supposed to signal in vt.

@@ -935,6 +994,30 @@ template <template <class...> class TypeCheck, class... Check>
using require_all_not_eigen_st
= require_all_not_t<is_eigen_scalar_check<TypeCheck, Check>...>;

template <template <class...> class TypeCheck, class... Check>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the s mean? I see is_eigen_matrix_scalar_check but I don't know what that means, either as it seems to be mixing types (matrix and scalar).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The st stands for scalar_type it's doc'd on the website

http://mc-stan.org/math/d1/db9/group__require__meta.html

This PR is already pretty big so I'm going to open up another PR to move these

@@ -39,17 +39,25 @@ TEST(MathMetaPrim, expression) {
EXPECT_FALSE((is_eigen_matrix<Eigen::EigenBase<Eigen::MatrixXd>>::value));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every metaprogram needs tests.

@bob-carpenter
Copy link
Contributor

@SteveBronder : Is something holding this up? I'd rather not leave PRs dangling for weeks with no activity.

@SteveBronder
Copy link
Collaborator Author

Apologies I've just been running around with job stuff I'll put fix this up today

@SteveBronder SteveBronder changed the title Expand definition of is_eigen_matrix Refactor Eigen Type traits Mar 4, 2020
@SteveBronder SteveBronder reopened this Mar 4, 2020
T, std::enable_if_t<internal::is_eigen_base<std::decay_t<T>>::value>>
struct is_eigen<T, std::enable_if_t<std::is_base_of<
Eigen::EigenBase<typename std::decay_t<T>::PlainObject>,
typename std::decay_t<T>::PlainObject>::value>>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a general comment, but it might make these templates more readable if the typename std::decay_t<T>::PlainObject is moved up to the template definition:

template <typename T, typename PlainType = typename std::decay_t<T>::PlainObject>
struct is_eigen<T, std::enable_if_t<std::is_base_of<
                       Eigen::EigenBase<PlainType>,
                       PlainType>::value>>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually idt this would work since it would set the default of the template value but I have to grab PlainObject in one specialization and MatrixType in another

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 4.79 4.87 0.98 -1.69% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 1.0 0.36% faster
eight_schools/eight_schools.stan 0.09 0.09 1.01 0.57% faster
gp_regr/gp_regr.stan 0.22 0.22 1.0 -0.34% slower
irt_2pl/irt_2pl.stan 6.44 6.5 0.99 -0.92% slower
performance.compilation 87.75 86.44 1.02 1.5% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.57 7.52 1.01 0.62% faster
pkpd/one_comp_mm_elim_abs.stan 20.4 20.51 0.99 -0.54% slower
sir/sir.stan 95.97 92.95 1.03 3.14% faster
gp_regr/gen_gp_data.stan 0.05 0.05 0.98 -1.66% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.96 2.95 1.0 0.28% faster
pkpd/sim_one_comp_mm_elim_abs.stan 0.33 0.31 1.05 4.51% faster
arK/arK.stan 1.74 1.75 1.0 -0.47% slower
arma/arma.stan 0.67 0.66 1.02 2.03% faster
garch/garch.stan 0.52 0.51 1.01 1.21% faster
Mean result: 1.00603338214

Jenkins Console Log
Blue Ocean
Commit hash: 16b9464


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@SteveBronder
Copy link
Collaborator Author

This is ready for review

template <typename T>
using is_eigen_matrix_or_array
= math::disjunction<is_eigen_matrix<std::decay_t<T>>,
is_eigen_array<std::decay_t<T>>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the change to is_eigen_matrix this does not make sense anymore. It should be renamed to is_eigen_matrix_or_vector_or_array ant the test should be changed appropriately.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the only place we are using is_eigen_matrix_or_array was in matrix_cl to check whether we should call .eval() or not. is_eigen_matrix_or_vector_or_array seems like kind of a mouthful. Should we just do is_eigen_dense in matrix_cl and get rid of this type trait?

Code that uses `is_eigen_matrix_or_array:
https://github.com/stan-dev/math/blob/develop/stan/math/opencl/matrix_cl.hpp#L312

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_eigen_dense is not the same thing! But I agree we can find a better name. This is actually checking whether something is a plain type so maybe is_eigen_plain_type?

@bob-carpenter
Copy link
Contributor

I'm a little confused as to who's reviewing this now. Should I do the final review now?

@t4c1
Copy link
Contributor

t4c1 commented Mar 11, 2020

@bob-carpenter go ahead with the review. I just had one comment.

@bob-carpenter
Copy link
Contributor

I don't understand what any of those metaprograms do, so I still want doc.

For example, I don't know what what the _vt means from my original review that's all over the place in require_genercs.

And I'm afraid I can't even parse these headers:

template <template <class...> class ContainerCheck,
          template <class...> class TypeCheck, class... Check>

I think you may need someone with more skill in templates to review this. I'm totally slammed right now and this whole file's full of things I don't understand.

@SteveBronder
Copy link
Collaborator Author

@t4c1 if this is too large to be nice to review I think I could break it up into at least 2 PRs with

  1. The testing framework and moving 1 or 2 type traits (like eig row and col vector)
  2. Then the rest

Or (2) could be broken up into 2 more PRs as well

@bob-carpenter
Copy link
Contributor

I can take a look at this if @t4c1 doesn't have time. Let me know.

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 4.86 4.88 0.99 -0.6% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 0.97 -3.25% slower
eight_schools/eight_schools.stan 0.09 0.09 1.0 -0.14% slower
gp_regr/gp_regr.stan 0.22 0.22 0.99 -1.43% slower
irt_2pl/irt_2pl.stan 6.49 6.46 1.0 0.37% faster
performance.compilation 88.29 87.35 1.01 1.06% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.54 7.53 1.0 0.11% faster
pkpd/one_comp_mm_elim_abs.stan 21.49 20.86 1.03 2.96% faster
sir/sir.stan 98.4 95.46 1.03 2.99% faster
gp_regr/gen_gp_data.stan 0.05 0.05 0.95 -4.92% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.97 2.96 1.0 0.29% faster
pkpd/sim_one_comp_mm_elim_abs.stan 0.32 0.31 1.05 4.44% faster
arK/arK.stan 1.74 1.74 1.0 -0.19% slower
arma/arma.stan 0.66 0.67 0.99 -1.36% slower
garch/garch.stan 0.52 0.51 1.01 0.79% faster
Mean result: 1.00126472362

Jenkins Console Log
Blue Ocean
Commit hash: e9ee8cc


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@t4c1
Copy link
Contributor

t4c1 commented Mar 31, 2020

@bob-carpenter I you want to review, go ahead. Otherwise I can do it.
@SteveBronder If I am reviewing, I would prefere this to be split in 2 or 3 PRs.

@SteveBronder
Copy link
Collaborator Author

I'm very fine with splitting this into 2 or 3 PRs

@bob-carpenter
Copy link
Contributor

If you could review, @tadej, that'd be great as I'm swamped as usual.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants