Skip to content

NMODL is slow in translating complicated models #3620

@JCGoran

Description

@JCGoran

Overview of the issue

Not a bug per se, but warrants a discussion. For this particular mod file https://github.com/ModelDBRepository/138382/blob/3548e4565608f7f61ea51ead2432e3f40bdf279e/cdp3.mod, NMODL takes over 7 minutes to just generate the code:

$ time nmodl --neuron cdp3.mod
real    7m11.235s
user    7m9.113s
sys     0m0.507s

My guess is that this is due to the KINETIC block being rather complex, and the resulting C++ file has almost 40000 lines.

On the other hand, nocmodl translates the file much faster:

$ time nocmodl cdp3.mod
real    0m0.089s
user    0m0.071s
sys     0m0.018s

Note that, for this particular model, compilation actually fails when using the NMODL translator, with the error (this is technically unrelated to the slowness, but it happens to the same model so I'm mentioning it for completeness):

/include/Eigen/src/Core/DenseStorage.h: In instantiation of ‘void Eigen::internal::check_static_allocation_size() [with T = double; int Size = 35721]’:
/include/Eigen/src/Core/DenseStorage.h:51:41:   required from ‘Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, Alignment>::plain_array() [with T = double; int Size = 35721; int MatrixOrArrayOptions = 0; int Alignment = 0]
’
/include/Eigen/src/Core/DenseStorage.h:211:38:   required from ‘Eigen::DenseStorage<T, Size, _Rows, _Cols, _Options>::DenseStorage() [with T = double; int Size = 35721; int _Rows = 189; int _Cols = 189; int _Options = 0]’
/include/Eigen/src/Core/PlainObjectBase.h:476:45:   required from ‘Eigen::PlainObjectBase<Derived>::PlainObjectBase() [with Derived = Eigen::Matrix<double, 189, 189>]’
/include/Eigen/src/Core/Matrix.h:259:21:   required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix() [with _Scalar = double; int _Rows = 189; int _Cols = 189; int _Options = 0; int _MaxRows = 189; int _MaxCols = 189]’
138382/AnwarEtAl2010/x86_64/cdp3.cpp:303:33:   required from ‘int nmodl::newton::newton_solver(Eigen::Matrix<double, N, 1>&, FUNC, double, int) [with int N = 189; FUNC = neuron::functor_cdp3_0]’
138382/AnwarEtAl2010/x86_64/cdp3.cpp:39091:65:   required from here
/include/Eigen/src/Core/DenseStorage.h:33:40: error: static assertion failed: OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
   33 |   EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
/include/Eigen/src/Core/DenseStorage.h:33:3: note: in expansion of macro ‘EIGEN_STATIC_ASSERT’
   33 |   EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
      |   ^~~~~~~~~~~~~~~~~~~
/include/Eigen/src/Core/DenseStorage.h:33:40: note: the comparison reduces to ‘(285768 <= 131072)’
   33 |   EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
/include/Eigen/src/Core/DenseStorage.h:33:3: note: in expansion of macro ‘EIGEN_STATIC_ASSERT’

The key line being:

note: the comparison reduces to ‘(285768 <= 131072)’

Since sizeof(T) is 8 on my machine, it seems the default limit for the an N x N matrix is N = 128. We can get around this issue by adding:

#define EIGEN_STACK_ALLOCATION_LIMIT 0

somewhere (I added it by hand to the file, but I'm sure we can add it as a flag to the nrnivmodl makefile).

Expected result/behavior

NMODL should not take so long to just translate the whole file. My suspicion is that the sympy solver, being written in pure Python, is rather slow for large systems.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions