1 /*
2 * send_buffer_position.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #ifndef SEND_BUFFER_POSITION_H
24 #define SEND_BUFFER_POSITION_H
25
26 // C++ includes:
27 #include <cassert>
28 #include <vector>
29 #include <limits>
30
31 // Includes from nestkernel:
32 #include "vp_manager.h"
33
34 namespace nest
35 {
36
37 /**
38 * This class simplifies keeping track of write position in MPI buffer
39 * while collocating spikes.
40 */
41 class SendBufferPosition
42 {
43 private:
44 thread begin_rank_;
45 thread end_rank_;
46 thread max_size_;
47 size_t num_spike_data_written_;
48 size_t send_recv_count_per_rank_;
49 std::vector< thread > idx_;
50 std::vector< thread > begin_;
51 std::vector< thread > end_;
52
53 thread rank_to_index_( const thread rank ) const;
54
55 public:
56 SendBufferPosition( const AssignedRanks& assigned_ranks, const unsigned int send_recv_count_per_rank );
57
58 /**
59 * Returns current index of specified rank in MPI buffer.
60 */
61 unsigned int idx( const thread rank ) const;
62
63 /**
64 * Returns begin index of specified rank in MPI buffer.
65 */
66 unsigned int begin( const thread rank ) const;
67
68 /**
69 * Returns end index of specified rank in MPI buffer.
70 */
71 unsigned int end( const thread rank ) const;
72
73 /**
74 * Returns whether the part of the buffer on the specified rank has been
75 * filled.
76 *
77 * @param rank Rank denoting which part of the buffer we check
78 */
79 bool is_chunk_filled( const thread rank ) const;
80
81 /**
82 * Returns whether the parts of the MPI buffer assigned to this thread has
83 * been filled.
84 */
85 bool are_all_chunks_filled() const;
86
87 void increase( const thread rank );
88 };
89
SendBufferPosition(const AssignedRanks & assigned_ranks,const unsigned int send_recv_count_per_rank)90 inline SendBufferPosition::SendBufferPosition( const AssignedRanks& assigned_ranks,
91 const unsigned int send_recv_count_per_rank )
92 : begin_rank_( assigned_ranks.begin )
93 , end_rank_( assigned_ranks.end )
94 , max_size_( assigned_ranks.max_size )
95 , num_spike_data_written_( 0 )
96 , send_recv_count_per_rank_( send_recv_count_per_rank )
97 {
98 idx_.resize( assigned_ranks.size );
99 begin_.resize( assigned_ranks.size );
100 end_.resize( assigned_ranks.size );
101 for ( thread rank = assigned_ranks.begin; rank < assigned_ranks.end; ++rank )
102 {
103 // thread-local index of (global) rank
104 const thread lr_idx = rank % assigned_ranks.max_size;
105 assert( lr_idx < assigned_ranks.size );
106 idx_[ lr_idx ] = rank * send_recv_count_per_rank;
107 begin_[ lr_idx ] = rank * send_recv_count_per_rank;
108 end_[ lr_idx ] = ( rank + 1 ) * send_recv_count_per_rank;
109 }
110 }
111
112 inline thread
rank_to_index_(const thread rank)113 SendBufferPosition::rank_to_index_( const thread rank ) const
114 {
115 assert( begin_rank_ <= rank );
116 assert( rank < end_rank_ );
117 return rank % max_size_;
118 }
119
120 inline unsigned int
idx(const thread rank)121 SendBufferPosition::idx( const thread rank ) const
122 {
123 return idx_[ rank_to_index_( rank ) ];
124 }
125
126 inline unsigned int
begin(const thread rank)127 SendBufferPosition::begin( const thread rank ) const
128 {
129 return begin_[ rank_to_index_( rank ) ];
130 }
131
132 inline unsigned int
end(const thread rank)133 SendBufferPosition::end( const thread rank ) const
134 {
135 return end_[ rank_to_index_( rank ) ];
136 }
137
138 inline bool
is_chunk_filled(const thread rank)139 SendBufferPosition::is_chunk_filled( const thread rank ) const
140 {
141 return idx( rank ) == end( rank );
142 }
143
144 inline bool
are_all_chunks_filled()145 SendBufferPosition::are_all_chunks_filled() const
146 {
147 return num_spike_data_written_ == send_recv_count_per_rank_ * idx_.size();
148 }
149
150 inline void
increase(const thread rank)151 SendBufferPosition::increase( const thread rank )
152 {
153 ++idx_[ rank_to_index_( rank ) ];
154 ++num_spike_data_written_;
155 }
156
157 } // namespace nest
158
159 #endif /* SEND_BUFFER_POSITION_H */
160