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

Add tutorial about homeostatic plasticity #2418

Closed

Conversation

thorstenhater
Copy link
Contributor

@thorstenhater thorstenhater commented Oct 3, 2024

Add a tutorial on how to engineer structural plasticity in Arbor using a homeostatic rule.
Read the preview here

https://arbor--2418.org.readthedocs.build/en/2418/tutorial/plasticity.html

Here's a teaser of the final result:
03-rates

Update: finished the tutorial.

@thorstenhater thorstenhater requested review from ErbB4 and jlubo October 3, 2024 09:36
@thorstenhater thorstenhater marked this pull request as ready for review October 8, 2024 09:56
thorstenhater and others added 12 commits October 14, 2024 10:51
Utter a dire warning for those who try to build with outdated and/or weird compilers.
XLC is no longer a thing, so we remove checking for it.
Some justifications:
- power & Co: only useful on Cray, likely outdated. Use external power measurements if this is relevant.
- trace.hpp was never used and was locked_ostream's only user.
This PR rectifies a long-standing issue since the introduction of
`decor`:
CV discretization was treated as a defaultable value instead of a cell
property, along with bio-physical properties.

This lead to some awkward facts:
- Intermingling of bio-physics and numerical settings
- Discretization is treated like a default without override.
- Discretization cannot be changed once set, e.g. if read from `.acc`,
requiring the copy+update of a decor instead

Thus:
- Discretization can now be set during `cable_cell` construction
- It can be read and updated later
- Refactor `cv_policy` to use type erasure like other, similar
constructions, e.g. schedules.
- Hide internal `cv_policy` constructors.

⚠️ Breaks `.acc` by upgrading from 0.9 to 0.10 ⚠️ 

Closes arbor-sim#1408

---------

Co-authored-by: boeschf <[email protected]>
This concludes the introduction of 'labels' for synapse identification /
placements started back in
PR arbor-sim#1504 by @noraabiakar. Labels are now used when probing a synapse's
state.
Bubbling up ion access information from modcc allows us to skip
allocation of `Xi` and `Xo` iff
no mechanism reads those values. 

A minor problem: Sampling may try to touch data that doesn't exist;
however who'd ask for `Xi`
if they never use it? 

Stacking this PR on top of arbor-sim#2393 the memory consumption drops by a
further 5% down to 77%
if the original value.

### Todo
- [x] Guard against sampling  non-existing `Xi`/`Xo`

---------

Co-authored-by: Jannik Luboeinski <[email protected]>
- fix event stream when more than one cell in a cell group have same
synapse
  - events would previously no longer necessarily be sorted by time
- in order to simplify: also sort with respect to mechanism index (as
was previously only required for the gpu backend)
  - add pertinent test
- while cleaning up: overhauled the event related files and data
structures
  - removed dead code
- made event handling less generic (this feature was not used anywhere)
# Introduction

- Do not allocate and fill storage for resetting ion concentrations if
these are never changed.
Reasoning: If concentrations are never changed, we do not reset them and
thus do not need
  to store the values. 
- Remove a duplicate of the CV area in solver and shared state and pass
a reference during solving
- Remove redundant `solution` from GPU solver
- Do not store / allocate diffusion values if not needed.

This saves **per CV**
- `1 x 8B` for `cv_area` unconditionally
- `1 x 8B` for `Xd` for each ion with no diffusion is in use (majority
of cases)
- `2 x 8B` for `Xi` for each ion (`reset` and `init`) if not written
(reasonably often)
- `2 x 8B` for `Xo` for each ion (`reset` and `init`) if not written
(majority of cases)
- `1 x 8B` for `eX` reset for each ion if not read (majority)
- `1 x 8B` for `eX` for each ion if not read (rarely)

In my standard benchmark, `busyring` with complex cells, this saves
about 18% of the total GPU
allocation for the cell data (`shared_state`).

This has become a mixed bag, fixing a few additional things that came up
during testing this:
- a bug in event handling on GPU
- pybind11 stub generation

---------

Co-authored-by: Jannik Luboeinski <[email protected]>
Co-authored-by: boeschf <[email protected]>
# Tree

Fixes --- likely a spurious --- warning in `tree.cpp`:
```
[2/6] Building CXX object arbor/CMakeFiles/arbor.dir/tree.cpp.o
In file included from /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/algorithm:60,
                 from /Users/hater/src/arbor/arbor/tree.cpp:1:
In function 'typename __gnu_cxx::__enable_if<std::__is_scalar<_Tp>::__value, void>::__type std::__fill_a1(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = unsigned int*; _Tp = unsigned int]',
    inlined from 'void std::__fill_a(_FIte, _FIte, const _Tp&) [with _FIte = unsigned int*; _Tp = unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algobase.h:998:21,
    inlined from '_OutputIterator std::__fill_n_a(_OutputIterator, _Size, const _Tp&, random_access_iterator_tag) [with _OutputIterator = unsigned int*; _Size = long unsigned int; _Tp = unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algobase.h:1151:20,
    inlined from '_OI std::fill_n(_OI, _Size, const _Tp&) [with _OI = unsigned int*; _Size = long unsigned int; _Tp = unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algobase.h:1180:29,
    inlined from 'static _ForwardIterator std::__uninitialized_default_n_1<true>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned int*; _Size = long unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_uninitialized.h:668:29,
    inlined from 'static _ForwardIterator std::__uninitialized_default_n_1<true>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned int*; _Size = long unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_uninitialized.h:660:9,
    inlined from '_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned int*; _Size = long unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_uninitialized.h:712:20,
    inlined from '_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, allocator<_Tp>&) [with _ForwardIterator = unsigned int*; _Size = long unsigned int; _Tp = unsigned int]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_uninitialized.h:779:44,
    inlined from 'void std::vector<_Tp, _Alloc>::_M_default_initialize(size_type) [with _Tp = unsigned int; _Alloc = std::allocator<unsigned int>]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_vector.h:1720:36,
    inlined from 'std::vector<_Tp, _Alloc>::vector(size_type, const allocator_type&) [with _Tp = unsigned int; _Alloc = std::allocator<unsigned int>]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_vector.h:558:30,
    inlined from 'arb::tree::iarray arb::tree::select_new_root(int_type)' at /Users/hater/src/arbor/arbor/tree.cpp:219:34:
/opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algobase.h:952:18: warning: 'void* __builtin_memset(void*, int, long unsigned int)' offset 4 is out of the bounds [0, 0] [-Warray-bounds=]
  952 |         *__first = __tmp;
```
Also use `iota` to generate contiguous indices.

# Tests

## `test_simd.cpp`

GCC doesn't acknowledge that `simd v[i] = x` for all `i = 0 ... len(v)`
initializes `v`. Force initialization to zero.

## `test_network_generation.cpp`

Compare across signs

## `test_distributed_for_each.cpp`

Compare across signs; resolve by casting to correct type.   

## `test_range.cpp`

GCC really turns the dial up to 11 here, complaining about oob access in
```
char str[] = "howdy";
auto rg = range_n(str, strlen(str)); // NOTE: Putting 5 here is OK, so is sizeof(str) - 1
util::sort(rg);
```
Same happens with `std::sort(str, str + strlen(str))`, so I am pretty
sure this is not a real thing.
For reference:
```
/Users/hater/src/arbor/test/unit/test_range.cpp: In member function 'virtual void range_sort_Test::TestBody()':
/Users/hater/src/arbor/test/unit/test_range.cpp:446:14: note: at offset [8, 4611686018427387903] into object 'cstr' of size 6
  446 |         char cstr[] = "howdy";
      |              ^~~~
In function 'std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]',
    inlined from 'void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from 'void std::__move_median_to_first(_Iterator, _Iterator, _Iterator, _Iterator, _Compare) [with _Iterator = char*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:91:20,
    inlined from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = char*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:1855:34,
    inlined from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = char*; _Size = long int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:1889:38,
    inlined from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = char*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:1905:25,
    inlined from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = char*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:1900:5,
    inlined from 'void std::sort(_RAIter, _RAIter) [with _RAIter = char*]' at /opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/stl_algo.h:4771:18,
    inlined from 'std::enable_if_t<((bool)(! std::is_const<typename arb::util::impl_seqtrait::sequence_traits<Seq&&>::reference>::value))> arb::util::sort(Seq&&) [with Seq = range<char*, char*>]' at /Users/hater/src/arbor/arbor/util/rangeutil.hpp:154:14,
    inlined from 'virtual void range_sort_Test::TestBody()' at /Users/hater/src/arbor/test/unit/test_range.cpp:448:19:
/opt/homebrew/Cellar/gcc/14.2.0/include/c++/14/bits/move.h:223:11: warning: array subscript [8, 4611686018427387903] is outside array bounds of 'char [6]' [-Warray-bounds=]
  223 |       __b = _GLIBCXX_MOVE(__tmp);
      |           ^
/Users/hater/src/arbor/test/unit/test_range.cpp: In member function 'virtual void range_sort_Test::TestBody()':
/Users/hater/src/arbor/test/unit/test_range.cpp:446:14: note: at offset [8, 4611686018427387903] into object 'cstr' of size 6
  446 |         char cstr[] = "howdy";
```

I am still going to 'fix' this, since I am for warning free code and
don't want to annotate with a pragma.

# General

Remove spurious includes.

---------

Co-authored-by: boeschf <[email protected]>
ErbB4
ErbB4 previously approved these changes Nov 11, 2024
ErbB4
ErbB4 previously approved these changes Nov 19, 2024
Copy link
Collaborator

@ErbB4 ErbB4 left a comment

Choose a reason for hiding this comment

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

This time with the C++ version?

@thorstenhater thorstenhater dismissed ErbB4’s stale review November 19, 2024 13:32

The merge-base changed after approval.

@thorstenhater
Copy link
Contributor Author

Ok, something weird happened during merging. I'll fix that.

ErbB4
ErbB4 previously approved these changes Nov 20, 2024
@thorstenhater thorstenhater dismissed ErbB4’s stale review November 20, 2024 10:34

The merge-base changed after approval.

ErbB4
ErbB4 previously approved these changes Nov 25, 2024
@thorstenhater thorstenhater dismissed ErbB4’s stale review November 25, 2024 11:40

The merge-base changed after approval.

@thorstenhater
Copy link
Contributor Author

Superseded by #2426 (same content, none of the merging mess)

@thorstenhater thorstenhater deleted the doc/plasticity-tutorial branch November 25, 2024 15:56
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.

3 participants