Skip to content

Commit 4666a7d

Browse files
authored
Merge pull request #227 from sy-c/master
v2.13.0
2 parents e98e19f + 2cad754 commit 4666a7d

12 files changed

+148
-8
lines changed

doc/configurationParameters.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ The parameters related to 3rd-party libraries are described here for convenience
106106
| equipment-* | memoryPoolNumberOfPages | int | | Number of pages to be created for this equipment, taken from the chosen memory bank. The bank should have enough free space to accomodate (memoryPoolNumberOfPages + 1) * memoryPoolPageSize bytes. |
107107
| equipment-* | memoryPoolPageSize | bytes | | Size of each memory page to be created. Some space might be kept in each page for internal readout usage. |
108108
| equipment-* | name | string| | Name used to identify this equipment (in logs). By default, it takes the name of the configuration section, equipment-xxx |
109+
| equipment-* | numaNode | string | auto | If set, memory / thread will try to use given NUMA node. If "auto", will try to guess it for given equipment (eg ROC). |
109110
| equipment-* | outputFifoSize | int | -1 | Size of output fifo (number of pages). If -1, set to the same value as memoryPoolNumberOfPages (this ensures that nothing can block the equipment while there are free pages). |
110111
| equipment-* | rdhCheckDetectorField | int | 0 | If set, the detector field is checked and changes reported. |
111112
| equipment-* | rdhCheckEnabled | int | 0 | If set, data pages are parsed and RDH headers checked. Errors are reported in logs. |

doc/releaseNotes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,6 @@ This file describes the main feature changes for each readout.exe released versi
477477
- added consumer-FairMQChannel-*.enablePackedCopy. If set, the same superpage may be reused (space allowing) for the copy of multiple HBF (instead of a separate one for each copy). This allows a reduced memoryPoolNumberOfPages.
478478
- ROC fifo health check enabled, a warning message is logged when in/out ROC FIFOs are empty/full.
479479

480+
## v2.13.0 - 11/08/2022
481+
- Updated configuration parameters:
482+
- added equipment-*.numaNode. If set, memory / thread will try to use given NUMA node. If "auto", will try to guess it for given equipment (eg ROC). "auto" is default.

src/ConsumerFMQchannel.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class ConsumerFMQchannel : public Consumer
255255
decDataBlockStats((*blockRef)->getData());
256256
delete blockRef;
257257
}
258-
},"",0,fair::mq::RegionConfig{true, true}); // lock / zero
258+
},fair::mq::RegionConfig{false,false}); // lock / zero - done later
259259

260260
theLog.log(LogInfoDevel_(3008), "Got FMQ unmanaged memory buffer size %lu @ %p", memoryBuffer->GetSize(), memoryBuffer->GetData());
261261
}

src/MemoryBankManager.cxx

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
// or submit itself to any jurisdiction.
1111

1212
#include "MemoryBankManager.h"
13+
#include "ReadoutUtils.h"
14+
#include <unistd.h>
15+
#include <sys/mman.h>
1316

1417
#include "readoutInfoLogger.h"
1518

@@ -35,7 +38,7 @@ int MemoryBankManager::addBank(std::shared_ptr<MemoryBank> bankPtr, std::string
3538
return 0;
3639
}
3740

38-
std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName, size_t firstPageOffset, size_t blockAlign)
41+
std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName, size_t firstPageOffset, size_t blockAlign, int numaNode)
3942
{
4043

4144
void* baseAddress = nullptr; // base address of bank from which the block is taken
@@ -92,6 +95,13 @@ std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize
9295
}
9396
}
9497

98+
// align at least to memory page
99+
int systemPageSize = getpagesize();
100+
if ((int)blockAlign < systemPageSize) {
101+
blockAlign = systemPageSize;
102+
theLog.log(LogInfoDevel,"Aligning memory block by default on system page size = %d bytes", systemPageSize);
103+
}
104+
95105
// align beginning of block as specified
96106
if (blockAlign > 0) {
97107
size_t bytesExcess = (((size_t)baseAddress) + offset) % blockAlign;
@@ -114,6 +124,36 @@ std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize
114124
}
115125
// end of locked block
116126

127+
if (numaNode >= 0) {
128+
// actual memory assignment is done on first write, in particular for FMQ
129+
// so set NUMA node and zero the memory to lock it
130+
// or try to move the block ?
131+
numaBind(numaNode);
132+
}
133+
134+
theLog.log(LogInfoDevel, "Zero memory");
135+
void *blockAddress = &(((char*)baseAddress)[offset]);
136+
// ensure pages stay in RAM
137+
// no need to lock them now, we write the full range on next line. keep them locked then. this is faster.
138+
mlock2(blockAddress, blockSize, MLOCK_ONFAULT);
139+
bzero(blockAddress, blockSize);
140+
theLog.log(LogInfoDevel, "Zero memory done");
141+
142+
if (numaNode >= 0) {
143+
numaBind(-1);
144+
}
145+
146+
int ptrNumaNode = -1;
147+
if (numaGetNodeFromAddress(blockAddress, ptrNumaNode) == 0) {
148+
theLog.log(LogInfoDevel, "Memory at %p is at node %d", blockAddress, ptrNumaNode);
149+
if (numaNode >= 0) {
150+
if (ptrNumaNode != numaNode) {
151+
theLog.log(LogWarningDevel, "Warning, could not allocate memory pool on requested NUMA node");
152+
// todo: try to move ?
153+
}
154+
}
155+
}
156+
117157
// create pool of pages from new block
118158
return std::make_shared<MemoryPagesPool>(pageSize, pageNumber, &(((char*)baseAddress)[offset]), blockSize, nullptr, firstPageOffset, newId);
119159
}

src/MemoryBankManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ class MemoryBankManager
4343
// - bankName: name of the bank from which to create the pool. If not specified, using the first bank.
4444
// - firstPageOffset: to control alignment of first page in pool. With zero, start from beginning of big block.
4545
// - blockAlign: alignment of beginning of big memory block from which pool is created. Pool will start at a multiple of this value.
46+
// - numaNode: if >= 0, try to allocate the pool on given NUMA node.
4647
// NB: trivial implementation, once a region from a bank has been used, it can not be reused after the corresponding pool of pages has been release ... don't want to deal with fragmentation etc
47-
std::shared_ptr<MemoryPagesPool> getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName = "", size_t firstPageOffset = 0, size_t blockAlign = 0);
48+
std::shared_ptr<MemoryPagesPool> getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName = "", size_t firstPageOffset = 0, size_t blockAlign = 0, int numaNode = -1);
4849

4950
// a struct to define a memory range
5051
struct memoryRange {

src/ReadoutEquipmentRORC.cxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// or submit itself to any jurisdiction.
1111

1212
#include <Common/Timer.h>
13+
#include <ReadoutCard/CardFinder.h>
1314
#include <ReadoutCard/ChannelFactory.h>
1415
#include <ReadoutCard/DmaChannelInterface.h>
1516
#include <ReadoutCard/Exception.h>
@@ -515,3 +516,12 @@ void ReadoutEquipmentRORC::finalCounters()
515516
}
516517
}
517518

519+
int getPreferredROCNumaNode(ConfigFile& cfg, std::string name) {
520+
try {
521+
std::string cardId = cfg.getValue<std::string>(name + ".cardId");
522+
return AliceO2::roc::findCard(cardId).numaNode;
523+
}
524+
catch (...) {
525+
}
526+
return -1;
527+
}

src/ReadoutUtils.cxx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
#include <filesystem>
1919

2020
#include "RAWDataHeader.h"
21+
#include "readoutInfoLogger.h"
22+
23+
#ifdef WITH_NUMA
24+
#include <numa.h>
25+
#include <numaif.h>
26+
#endif
2127

2228
// function to convert a string to a 64-bit integer value
2329
// allowing usual "base units" in suffix (k,M,G,T)
@@ -256,3 +262,39 @@ int getStatsFilesystem(unsigned long long &freeBytes, const std::string &path) {
256262
return 0;
257263
}
258264

265+
int numaBind(int numaNode) {
266+
#ifdef WITH_NUMA
267+
struct bitmask* nodemask = nullptr;
268+
if (numaNode>=0) {
269+
nodemask = numa_allocate_nodemask();
270+
if (nodemask != nullptr) {
271+
theLog.log(LogInfoDevel, "Enforcing memory allocated on NUMA node %d", numaNode);
272+
numa_bitmask_clearall(nodemask);
273+
numa_bitmask_setbit(nodemask, numaNode);
274+
numa_bind(nodemask);
275+
numa_free_nodemask(nodemask);
276+
return 0;
277+
}
278+
} else {
279+
nodemask = numa_get_mems_allowed();
280+
numa_bind(nodemask);
281+
theLog.log(LogInfoDevel, "Releasing memory NUMA node enforcement");
282+
return 0;
283+
}
284+
//numa_set_membind(nodemask);
285+
#endif
286+
return -1;
287+
}
288+
289+
int numaGetNodeFromAddress(void *ptr, int &node) {
290+
#ifdef WITH_NUMA
291+
int err;
292+
node = -1;
293+
err = move_pages(0, 1, &ptr, NULL, &node, 0);
294+
if (!err) {
295+
return 0;
296+
}
297+
// EFAULT -> memory not mapped yet
298+
#endif
299+
return -1;
300+
}

src/ReadoutUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ int getStatsMemory(unsigned long long &freeBytes, const std::string& keyword);
7171
// returns 0 on success, -1 on error
7272
int getStatsFilesystem(unsigned long long &freeBytes, const std::string& path);
7373

74+
// function to bind CPU / MEM to specific numa node
75+
// Use numaNode = -1 to bind to any / unbind.
76+
// returns 0 on success, or an error code.
77+
int numaBind(int numaNode);
78+
79+
// function to get NUMA node of where given pointer is allocated
80+
// returns 0 on success, or an error code
81+
int numaGetNodeFromAddress(void *ptr, int &node);
82+
7483
// end of _READOUTUTILS_H
7584
#endif
7685

src/ReadoutVersion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12-
#define READOUT_VERSION "2.12.0"
12+
#define READOUT_VERSION "2.13.0"
1313

src/ZmqClient.cxx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
#include <functional>
1515
#include <zmq.h>
1616

17-
#include <InfoLogger/InfoLogger.hxx>
18-
#include <InfoLogger/InfoLoggerMacros.hxx>
19-
using namespace AliceO2::InfoLogger;
20-
extern InfoLogger theLog;
17+
#include "readoutInfoLogger.h"
2118

2219
ZmqClient::ZmqClient(const std::string& url, int maxMsgSize, int zmqMaxQueue)
2320
{

0 commit comments

Comments
 (0)