Skip to content

Commit b3968ae

Browse files
authored
Merge branch 'master' into feat/cppDynamicArray
2 parents 42a7c3f + 3f66e88 commit b3968ae

File tree

14 files changed

+133
-46
lines changed

14 files changed

+133
-46
lines changed

.github/workflows/post_release_updates.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
contents: write
1212
pull-requests: write
1313
steps:
14-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
14+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
1515
with:
1616
persist-credentials: true # Needed to push changes back to the repository
1717
fetch-depth: 0

.github/workflows/publish.yml

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
matrix:
2525
os: [ windows-latest, macOS-13, macOS-14 ]
2626
steps:
27-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
27+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
2828
with:
2929
fetch-depth: 0
3030
persist-credentials: false
@@ -44,17 +44,15 @@ jobs:
4444
f.write(f"dir={str(user_cache_path(appname='cibuildwheel', appauthor='pypa'))}")
4545
shell: python
4646
- name: Cache cibuildwheel tools
47-
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
47+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
4848
with:
4949
path: ${{ steps.cibuildwheel-cache.outputs.dir }}
5050
key: ${{ runner.os }}-cibuildwheel
5151
- name: Build wheels
52-
uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
52+
uses: pypa/cibuildwheel@c923d83ad9c1bc00211c5041d0c3f73294ff88f6 # v3.1.4
5353
env:
5454
CIBW_PROJECT_REQUIRES_PYTHON: ">=${{ needs.get_python_versions.outputs.min-python }}"
5555
CIBW_ARCHS: auto64
56-
# Do not build for PyPy
57-
CIBW_SKIP: 'pp*'
5856
CIBW_TEST_COMMAND: python {project}/dev/continuous-integration/run_simple_test.py
5957
CIBW_TEST_REQUIRES: pytest
6058
with:
@@ -75,7 +73,7 @@ jobs:
7573
config: [{arch: auto64, image: ubuntu-24.04},
7674
{arch: aarch64, image: ubuntu-24.04-arm}]
7775
steps:
78-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
76+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
7977
with:
8078
fetch-depth: 0
8179
persist-credentials: false
@@ -100,12 +98,12 @@ jobs:
10098
f.write(f"dir={str(user_cache_path(appname='cibuildwheel', appauthor='pypa'))}")
10199
shell: python
102100
- name: Cache cibuildwheel tools
103-
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
101+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
104102
with:
105103
path: ${{ steps.cibuildwheel-cache.outputs.dir }}
106104
key: ${{ matrix.config.image }}-${{ matrix.config.arch }}-cibuildwheel
107105
- name: Build wheels
108-
uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
106+
uses: pypa/cibuildwheel@c923d83ad9c1bc00211c5041d0c3f73294ff88f6 # v3.1.4
109107
env:
110108
CIBW_PROJECT_REQUIRES_PYTHON: ">=${{ needs.get_python_versions.outputs.min-python }}"
111109
CIBW_ARCHS_LINUX: ${{ matrix.config.arch }}
@@ -133,7 +131,7 @@ jobs:
133131
- build-linux
134132
steps:
135133
- name: load distribution 📦
136-
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
134+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
137135
with:
138136
pattern: packages-*
139137
merge-multiple: true
@@ -155,7 +153,7 @@ jobs:
155153
- build-linux
156154
steps:
157155
- name: load distribution 📦
158-
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
156+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
159157
with:
160158
pattern: packages-*
161159
merge-multiple: true
@@ -171,13 +169,13 @@ jobs:
171169
if: ${{ github.event_name == 'push' || (github.event.pull_request.author_association == 'COLLABORATOR' || github.event.pull_request.author_association == 'OWNER') }}
172170
steps:
173171
- name: Checkout repository
174-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
172+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
175173
with:
176174
persist-credentials: false
177175
# https://github.com/actions/checkout/
178176
- name: Docker meta
179177
id: meta
180-
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
178+
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
181179
# https://github.com/docker/metadata-action
182180
with:
183181
images: |
@@ -203,20 +201,20 @@ jobs:
203201
# https://github.com/docker/setup-buildx-action
204202
- name: Login to DockerHub
205203
if: ${{ github.event_name == 'push' && github.repository == 'brian-team/brian2' && github.actor != 'dependabot[bot]'}}
206-
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
204+
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
207205
# https://github.com/docker/login-action
208206
with:
209207
username: ${{ secrets.DOCKERHUB_USERNAME }}
210208
password: ${{ secrets.DOCKERHUB_TOKEN }}
211209
- name: Login to GitHub Container Registry
212210
if: ${{ github.event_name == 'push' && github.repository == 'brian-team/brian2' && github.actor != 'dependabot[bot]'}}
213-
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
211+
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
214212
with:
215213
registry: ghcr.io
216214
username: ${{ github.repository_owner }}
217215
password: ${{ secrets.GITHUB_TOKEN }}
218216
- name: load Linux x86 distribution 📦
219-
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
217+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
220218
with:
221219
pattern: packages-linux-*
222220
merge-multiple: true

.github/workflows/static_analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
security-events: write
1414
steps:
1515
- name: Checkout repository
16-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
16+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
1717
with:
1818
persist-credentials: false
1919
- name: Install the latest version of uv

.github/workflows/test_latest.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838

3939
steps:
4040
- name: Checkout Repository
41-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
41+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
4242
with:
4343
fetch-depth: 0
4444
persist-credentials: false
@@ -105,7 +105,7 @@ jobs:
105105

106106
steps:
107107
- name: Checkout Repository
108-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
108+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
109109
with:
110110
fetch-depth: 0
111111
persist-credentials: false
@@ -151,7 +151,7 @@ jobs:
151151
echo "Cython cache dir: $CACHE_DIR"
152152
echo "cachedir=$CACHE_DIR" >> "$GITHUB_OUTPUT"
153153
- name: restore Cython cache
154-
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
154+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
155155
if: ${{ ! matrix.standalone }}
156156
with:
157157
key: cython-extensions-latest-${{ matrix.os }}-${{ matrix.python-version }}-32bit-${{ matrix.float_dtype_32 }}

.github/workflows/testsuite.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
name: Run linters with pre-commit
2121
runs-on: ubuntu-latest
2222
steps:
23-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
2424
with:
2525
persist-credentials: false
2626
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@@ -65,7 +65,7 @@ jobs:
6565
shell: bash -l {0}
6666
steps:
6767
- name: Checkout Repository
68-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
68+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
6969
with:
7070
fetch-depth: 0
7171
persist-credentials: false
@@ -108,7 +108,7 @@ jobs:
108108
PYTHON_BINARY: ${{ steps.python.outputs.python-path }}
109109

110110
- name: restore Cython cache
111-
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
111+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
112112
if: ${{ ! matrix.standalone }}
113113
with:
114114
key: cython-extensions-${{ matrix.os.image }}-${{ matrix.python-version }}-32bit-${{ matrix.float_dtype_32 }}
@@ -152,12 +152,12 @@ jobs:
152152
run:
153153
shell: bash -l {0}
154154
steps:
155-
- name: Checkout Repository
156-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
157-
with:
158-
fetch-depth: 0
159-
persist-credentials: false
160-
submodules: true
155+
- name: Checkout Repository
156+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
157+
with:
158+
fetch-depth: 0
159+
persist-credentials: false
160+
submodules: true
161161

162162
- name: Setup Conda and Python
163163
uses: conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f # v3.2.0

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ Samuele De Cristofaro (@Samuele-DeCristofaro)
5353
Sagar Shahari (@maverick4code)
5454
Palash Chitnavis (@PalashChitnavis)
5555
Mrigesh Thakur (@Legend101Zz)
56+
Liam Keegan (@lkeegan)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ If you use Brian for your published research, we kindly ask you to cite our arti
3030
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)
3131
[![Discourse topics](https://img.shields.io/discourse/topics?server=https%3A%2F%2Fbrian.discourse.group)](https://brian.discourse.group)
3232
[![Discourse chat](https://img.shields.io/badge/discourse-chat-4EC820?logo=discourse&link=https%3A%2F%2Fbrian.discourse.group%2Fchat)](https://brian.discourse.group/chat)
33+
[![Neuromorphic Computing](https://img.shields.io/badge/Collaboration_Network-Open_Neuromorphic-blue)](https://open-neuromorphic.org/neuromorphic-computing/)
3334
[![code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
3435

3536
## Quickstart
Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,55 @@
1-
{# USES_VARIABLES { _queue } #}
1+
{# USES_VARIABLES { _queue_capsule } #}
22
{% extends 'common_group.pyx' %}
33

4+
{% block template_support_code %}
5+
from cpython.pycapsule cimport PyCapsule_GetPointer
6+
from libcpp.vector cimport vector
7+
from cython.operator cimport dereference
8+
# We declare minimal C++ interface here - only methods we actually want to use
9+
# This avoids importing the full SpikeQueue wrapper and its dependencies
10+
cdef extern from "cspikequeue.cpp":
11+
cdef cppclass CSpikeQueue:
12+
vector[int32_t]* peek();
13+
void advance();
14+
{% endblock %}
15+
416
{% block maincode %}
5-
cdef _numpy.ndarray[int32_t, ndim=1, mode='c'] _spiking_synapses = _queue.peek()
17+
# Extract the raw C++ object pointer from the Python capsule.
18+
cdef object capsule = _queue_capsule
19+
cdef CSpikeQueue* cpp_queue = <CSpikeQueue*>PyCapsule_GetPointer(capsule, "CSpikeQueue")
20+
21+
# Now we call the C++ peek method directly to get the current spike vector.
22+
# This returns a pointer to std::vector<int32_t> containing synapse IDs
23+
# that are ready for processing in the current time step.
24+
cdef vector[int32_t]* spike_vector = cpp_queue.peek()
25+
cdef size_t num_spikes = dereference(spike_vector).size()
26+
27+
# Early exit for empty queue - avoid all processing overhead
28+
if num_spikes == 0:
29+
cpp_queue.advance()
30+
return
31+
32+
# Access the underlying raw data pointer of the vector
33+
cdef int32_t* spike_data = &dereference(spike_vector)[0]
634

735
# scalar code
836
_vectorisation_idx = 1
937
{{ scalar_code | autoindent }}
1038

11-
cdef size_t _spiking_synapse_idx
1239

13-
for _spiking_synapse_idx in range(len(_spiking_synapses)):
14-
# vector code
15-
_idx = _spiking_synapses[_spiking_synapse_idx]
40+
cdef size_t i = 0
41+
cdef int32_t synapse_id
42+
while i < num_spikes:
43+
synapse_id = spike_data[i]
44+
45+
_idx = synapse_id
1646
_vectorisation_idx = _idx
47+
1748
{{ vector_code | autoindent }}
1849

19-
# Advance the spike queue
20-
_queue.advance()
50+
i += 1
51+
52+
# Move the queue forward to the next time step
53+
cpp_queue.advance()
2154

2255
{% endblock %}
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
1+
{# USES_VARIABLES { _queue_capsule } #}
12
{% extends 'common_group.pyx' %}
23

4+
{% block template_support_code %}
5+
from cpython.pycapsule cimport PyCapsule_GetPointer
6+
# We declare minimal C++ interface here - only methods we actually want to use
7+
# This avoids importing the full SpikeQueue wrapper and its dependencies
8+
cdef extern from "cspikequeue.cpp":
9+
cdef cppclass CSpikeQueue:
10+
void push(int32_t *, int)
11+
{% endblock %}
12+
313
{% block before_code %}
414
_owner.initialise_queue()
515
{% endblock %}
616

717
{% block maincode %}
8-
_owner.push_spikes()
18+
{% set eventspace=get_array_name(eventspace_variable)%}
19+
cdef int spike_count
20+
# Get the spike count from the last entry in the spike buffer
21+
spike_count = {{eventspace}}[_num{{eventspace}}-1]
22+
23+
# Recover the C++ spike queue object from the PyCapsule passed at runtime
24+
cdef object capsule = _queue_capsule
25+
cdef CSpikeQueue* cpp_queue = <CSpikeQueue*>PyCapsule_GetPointer(capsule, "CSpikeQueue")
26+
27+
if spike_count > 0:
28+
# Optimized: avoid the push_spikes method call overhead
29+
cpp_queue.push({{eventspace}},spike_count)
930
{% endblock %}

brian2/core/variables.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1594,8 +1594,16 @@ def __hash__(self):
15941594
# Get access to some basic properties of the underlying array
15951595
@property
15961596
def shape(self):
1597+
if isinstance(self.variable, DynamicArrayVariable):
1598+
# For dynamic variables, we need to make sure that their size is up-to-date in standalone mode
1599+
# We can trigger the update by asking for the values, even though we don't need them here
1600+
self.variable.get_value()
15971601
if self.ndim == 1:
1598-
if not self.variable.scalar:
1602+
if (
1603+
hasattr(self, "group")
1604+
and hasattr(self.group, "start")
1605+
and hasattr(self.group, "stop")
1606+
):
15991607
# This is safer than using the variable size, since it also works for subgroups
16001608
# see GitHub issue #1555
16011609
size = self.group.stop - self.group.start

0 commit comments

Comments
 (0)