2424#pragma once
2525
2626#include < cstring>
27- #include " pthread.h"
27+ #include < pthread.h>
28+
2829#include < hicr/core/communicationManager.hpp>
2930#include < hicr/core/localMemorySlot.hpp>
3031#include < hicr/backends/hwloc/globalMemorySlot.hpp>
3132
33+ #include " sharedMemory.hpp"
34+
3235namespace HiCR ::backend::pthreads
3336{
3437
@@ -42,43 +45,24 @@ class CommunicationManager final : public HiCR::CommunicationManager
4245 public:
4346
4447 /* *
45- * Constructor for the memory manager class for the Pthreads backend
48+ * Constructor for the communication manager class for the pthreads backend
4649 *
47- * \param[in] fenceCount Specifies how many times a fence has to be called for it to release callers
50+ * \param[in] sharedMemory the shared memory used to exchange global slots among other threads
4851 */
49- CommunicationManager (const size_t fenceCount = 1 )
50- : HiCR::CommunicationManager()
51- {
52- // Initializing barrier for fence operation
53- pthread_barrier_init (&_barrier, nullptr , fenceCount);
54-
55- // Initializing mutex object
56- pthread_mutex_init (&_mutex, nullptr );
57- }
52+ CommunicationManager (SharedMemory &sharedMemory)
53+ : HiCR::CommunicationManager(),
54+ _sharedMemory (sharedMemory)
55+ {}
5856
5957 /* *
6058 * The destructor deletes all created barrier/mutex locks
6159 */
62- ~CommunicationManager () override
63- {
64- // Freeing barrier memory
65- pthread_barrier_destroy (&_barrier);
66-
67- // Freeing mutex memory
68- pthread_mutex_destroy (&_mutex);
69- }
60+ ~CommunicationManager () = default ;
7061
7162 __INLINE__ std::shared_ptr<HiCR::GlobalMemorySlot> getGlobalMemorySlotImpl (const HiCR::backend::hwloc::GlobalMemorySlot::tag_t tag,
7263 const HiCR::backend::hwloc::GlobalMemorySlot::globalKey_t globalKey) override
7364 {
74- if (_shadowMap.find (tag) != _shadowMap.end ())
75- {
76- if (_shadowMap[tag].find (globalKey) != _shadowMap[tag].end ())
77- return _shadowMap[tag][globalKey];
78- else
79- return nullptr ;
80- }
81- else { return nullptr ; }
65+ return _sharedMemory.get (tag, globalKey);
8266 }
8367
8468 /* *
@@ -110,21 +94,8 @@ class CommunicationManager final : public HiCR::CommunicationManager
11094
11195 private:
11296
113- /* *
114- * Stores a barrier object to check on a barrier operation
115- */
116- pthread_barrier_t _barrier{};
117-
118- /* *
119- * A mutex to make sure threads do not bother each other during certain operations
120- */
121- pthread_mutex_t _mutex{};
122-
12397 __INLINE__ void exchangeGlobalMemorySlotsImpl (const HiCR::GlobalMemorySlot::tag_t tag, const std::vector<globalKeyMemorySlotPair_t> &memorySlots) override
12498 {
125- // Synchronize all intervening threads in this call
126- barrier ();
127-
12899 // Simply adding local memory slots to the global map
129100 for (const auto &entry : memorySlots)
130101 {
@@ -139,29 +110,23 @@ class CommunicationManager final : public HiCR::CommunicationManager
139110
140111 // Registering memory slot
141112 registerGlobalMemorySlot (globalMemorySlot);
142- _shadowMap[tag][globalKey] = globalMemorySlot;
143- }
144113
145- // Do not allow any thread to continue until the exchange is made
146- barrier ();
114+ // Push it to shared memory
115+ _sharedMemory.insert (tag, globalKey, globalMemorySlot);
116+ }
147117 }
148118
149119 __INLINE__ void queryMemorySlotUpdatesImpl (std::shared_ptr<HiCR::LocalMemorySlot> memorySlot) override
150120 {
151121 // This function should check and update the abstract class for completed memcpy operations
152122 }
153123
154- /* *
155- * A barrier implementation that synchronizes all threads in the HiCR instance
156- */
157- __INLINE__ void barrier () { pthread_barrier_wait (&_barrier); }
158-
159124 /* *
160125 * Implementation of the fence operation for the pthreads backend. In this case, nothing needs to be done, as
161126 * the system's memcpy operation is synchronous. This means that it's mere execution (whether immediate or deferred)
162127 * ensures its completion.
163128 */
164- __INLINE__ void fenceImpl (const HiCR::GlobalMemorySlot::tag_t tag) override { barrier (); }
129+ __INLINE__ void fenceImpl (const HiCR::GlobalMemorySlot::tag_t tag) override { _sharedMemory. barrier (); }
165130
166131 __INLINE__ void memcpyImpl (const std::shared_ptr<HiCR::LocalMemorySlot> &destination,
167132 const size_t dst_offset,
@@ -193,7 +158,7 @@ class CommunicationManager final : public HiCR::CommunicationManager
193158 */
194159 __INLINE__ void destroyGlobalMemorySlotImpl (std::shared_ptr<HiCR::GlobalMemorySlot> memorySlot) override
195160 {
196- // Nothing to do here
161+ _sharedMemory. remove (memorySlot-> getGlobalTag (), memorySlot-> getGlobalKey ());
197162 }
198163
199164 __INLINE__ void memcpyImpl (const std::shared_ptr<HiCR::GlobalMemorySlot> &destination,
@@ -202,17 +167,11 @@ class CommunicationManager final : public HiCR::CommunicationManager
202167 const size_t src_offset,
203168 const size_t size) override
204169 {
205- // Getting up-casted pointer for the execution unit
206- auto dst = dynamic_pointer_cast<HiCR::GlobalMemorySlot>(destination);
207-
208- // Checking whether the execution unit passed is compatible with this backend
209- if (dst == nullptr ) HICR_THROW_LOGIC (" The passed destination memory slot is not supported by this backend\n " );
210-
211170 // Checking whether the memory slot is local. This backend only supports local data transfers
212- if (dst ->getSourceLocalMemorySlot () == nullptr ) HICR_THROW_LOGIC (" The passed destination memory slot is not local (required by this backend)\n " );
171+ if (destination ->getSourceLocalMemorySlot () == nullptr ) HICR_THROW_LOGIC (" The passed destination memory slot is not local (required by this backend)\n " );
213172
214173 // Executing actual memcpy
215- memcpy (dst ->getSourceLocalMemorySlot (), dst_offset, source, src_offset, size);
174+ memcpy (destination ->getSourceLocalMemorySlot (), dst_offset, source, src_offset, size);
216175
217176 // Increasing message received/sent counters for both memory slots
218177 increaseMessageRecvCounter (*destination->getSourceLocalMemorySlot ());
@@ -225,17 +184,11 @@ class CommunicationManager final : public HiCR::CommunicationManager
225184 const size_t src_offset,
226185 const size_t size) override
227186 {
228- // Getting up-casted pointer for the execution unit
229- auto src = dynamic_pointer_cast<HiCR::GlobalMemorySlot>(source);
230-
231- // Checking whether the memory slot is compatible with this backend
232- if (src == nullptr ) HICR_THROW_LOGIC (" The passed source memory slot is not supported by this backend\n " );
233-
234187 // Checking whether the memory slot is local. This backend only supports local data transfers
235- if (src ->getSourceLocalMemorySlot () == nullptr ) HICR_THROW_LOGIC (" The passed source memory slot is not local (required by this backend)\n " );
188+ if (source ->getSourceLocalMemorySlot () == nullptr ) HICR_THROW_LOGIC (" The passed source memory slot is not local (required by this backend)\n " );
236189
237190 // Executing actual memcpy
238- memcpy (destination, dst_offset, src ->getSourceLocalMemorySlot (), src_offset, size);
191+ memcpy (destination, dst_offset, source ->getSourceLocalMemorySlot (), src_offset, size);
239192
240193 // Increasing message received/sent counters for both memory slots
241194 increaseMessageRecvCounter (*destination);
@@ -266,24 +219,12 @@ class CommunicationManager final : public HiCR::CommunicationManager
266219 m->unlock ();
267220 }
268221
269- __INLINE__ void lock ()
270- {
271- // Locking the pthread mutex
272- pthread_mutex_lock (&_mutex);
273- }
274-
275- __INLINE__ void unlock ()
276- {
277- // Locking the pthread mutex
278- pthread_mutex_unlock (&_mutex);
279- }
280-
281222 private:
282223
283- // this map shadows the core HiCR map _globalMemorySlotTagKeyMap
284- // to support getGlobalMemorySlot implementation
285- // for this backend
286- globalMemorySlotTagKeyMap_t _shadowMap ;
224+ /* *
225+ * Shared Memory to exchange slots
226+ */
227+ SharedMemory &_sharedMemory ;
287228};
288229
289230} // namespace HiCR::backend::pthreads
0 commit comments