Skip to content

Commit 593679c

Browse files
committed
clean up thread remapping
1 parent f9b82a1 commit 593679c

1 file changed

Lines changed: 75 additions & 118 deletions

File tree

src/sst/elements/ariel/frontend/pin3/fesimple.cc

Lines changed: 75 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,6 @@ struct timespec offset_tp_mono;
145145
struct timespec offset_tp_real;
146146
#endif
147147

148-
// MPI
149-
int api_mpi_init_used = 0;
150-
151148
/****************************************************************/
152149
/********************** SHADOW STACK ****************************/
153150
/* Used by 'sieve' to associate mallocs to the code they */
@@ -183,93 +180,88 @@ class StackRecord {
183180

184181
std::vector<std::vector<StackRecord> > arielStack; // Per-thread stacks
185182

183+
184+
185+
// Returns true iff "libmpi.so" or "libmpi_cray.so" is found
186+
// in the call stack, indicating that the calling thread is
187+
// currently inside an MPI library. We use this information
188+
// to remap the mpi thread ids to come after the app threads.
186189
static const UINT32 MAX_FRAMES = 64;
187190
bool is_mpi_thread(CONTEXT* ctxt) {
188-
void *buf[256];
191+
void *buf[2048];
189192

190193
// PIN_Backtrace fills the trace array with return addresses.
191194
// numFrames holds the number of captured frames.
192195
UINT32 numFrames = PIN_Backtrace(ctxt, buf, sizeof(buf) / sizeof(buf[0]));
193-
//std::cout << "numFrames: " << numFrames << std::endl;
194196

195-
for (UINT32 i = 0; i < numFrames; i++)
196-
{
197+
for (UINT32 i = 0; i < numFrames; i++) {
197198
// Get the image (module) that contains the current address.
198199
IMG img = IMG_FindByAddress((ADDRINT)buf[i]);
199-
if (IMG_Valid(img))
200-
{
201-
// Retrieve the image name as a std::string.
200+
201+
if (IMG_Valid(img)) {
202202
std::string imgName = IMG_Name(img);
203-
//std::cout << "imgName: " << imgName << std::endl;
203+
204204
// Check if "libmpi.so" appears in the module name.
205-
if (imgName.find("libmpi.so") != std::string::npos)
206-
{
205+
// Also check for libmpi_cray.so, just in case
206+
if ((imgName.find("libmpi.so") != std::string::npos) ||
207+
(imgName.find("libmpi_cray.so") != std::string::npos)) {
207208
return true;
208209
}
209210
}
210211
}
211212
return false;
212213
}
213214

214-
UINT32 num_threads;
215215

216-
// Used for synchronizing access to the thread id map
216+
// Would be more efficient to implement as a TLS_KEY,
217+
// but it is rarely written so false sharing should not
218+
// be an issue
217219
std::unordered_map<THREADID, THREADID> remap_id;
218220

219-
TLS_KEY syscall_id;
220-
TLS_KEY clone_is_mpi;
221-
TLS_KEY _os_tid;
222-
VOID ThreadStart(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID* v) {
223-
// Initialize data for storing syscall number as it is only availble on Entry, not Exit
224-
PIN_SetThreadData(syscall_id, new ADDRINT(0), tid);
225-
PIN_SetThreadData(clone_is_mpi, new bool(false), tid);
226-
227-
//PIN_SetThreadData(_os_tid, new ADDRINT(0), tid);
228-
}
229-
/*
230-
VOID ThreadFini(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID* v) {
231-
// Delete thread local storage
232-
ADDRINT *syscallNum = static_cast<ADDRINT *>(PIN_GetThreadData(tlsKey, threadId));
233-
delete syscallNum;
221+
std::atomic<UINT32> next_app_thread{0};
222+
std::atomic<UINT32> next_mpi_thread{0};
223+
std::atomic<UINT32> num_threads{0};
224+
225+
// Initialize data used for remapping thread IDs
226+
VOID init_remapping_data(UINT32 core_count) {
227+
remap_id[0] = 0;
228+
next_app_thread = 1;
229+
next_mpi_thread = core_count;
230+
num_threads = 1;
234231
}
235-
*/
236-
UINT32 next_app_thread;
237-
UINT32 next_mpi_thread;
238232

239-
VOID SyscallEntry(THREADID threadid, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
233+
VOID SyscallEntry(THREADID tid, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
240234
{
241-
// Retrieve the system call number.
242235
PIN_LockClient();
243236
ADDRINT scNo = PIN_GetSyscallNumber(ctxt, std);
244-
ADDRINT *syscall_id_ptr = static_cast<ADDRINT *>(PIN_GetThreadData(syscall_id, threadid));
245-
*syscall_id_ptr = scNo;
246-
247-
248-
bool is_mpi = false;
249-
if (scNo == SYS_clone || scNo == __NR_clone)
250-
{
251-
PIN_GetLock(&mainLock, threadid);
252-
UINT32 next_thread = num_threads;
253-
num_threads++;
254-
255-
bool is_mpi = is_mpi_thread(ctxt);
256-
std::cout << "next_thread is " << next_thread << std::endl;
257-
if (is_mpi) {
258-
remap_id[next_thread] = next_mpi_thread++;
259-
} else {
260-
remap_id[next_thread] = next_app_thread++;
261-
}
262-
PIN_ReleaseLock(&mainLock);
263-
264-
std::cout << "--------------\n";
265-
for (const auto& pair : remap_id) {
266-
std::cout << " --> " << pair.first << " -- " << pair.second << std::endl;
267-
}
268-
std::cout << "--------------\n";
269237

238+
if (scNo == SYS_clone || scNo == __NR_clone) {
239+
PIN_GetLock(&mainLock, tid);
240+
241+
// Get the next thread id
242+
UINT32 next_thread = num_threads.fetch_add(1);
243+
244+
bool is_mpi = is_mpi_thread(ctxt);
245+
246+
// App threads will be numbered 0..num_cores-1
247+
// MPI library threads will be numbered num_cores..
248+
if (is_mpi) {
249+
remap_id[next_thread] = next_mpi_thread.fetch_add(1);
250+
} else {
251+
remap_id[next_thread] = next_app_thread.fetch_add(1);
252+
}
253+
PIN_ReleaseLock(&mainLock);
254+
255+
#ifdef ARIEL_DEBUG
256+
fprintf(stderr, "Caught clone syscall. Launching thread %d (MPI?: %d). Current thread map is:\n", next_thread, is_mpi);
257+
for (const auto& pair : remap_id) {
258+
259+
std::cout << "[ " << pair.first << " -> " << pair.second << " ]\n";
260+
}
261+
#endif
270262
}
271-
bool *clone_is_mpi_ptr = static_cast<bool *>(PIN_GetThreadData(clone_is_mpi, threadid));
272-
*clone_is_mpi_ptr = is_mpi;
263+
264+
273265
PIN_UnlockClient();
274266
}
275267

@@ -439,7 +431,7 @@ VOID WriteFlushInstructionMarker(UINT32 thr, ADDRINT ip, ADDRINT vaddr)
439431
ac.instPtr = (uint64_t) ip;
440432
ac.flushline.vaddr = (uint32_t) vaddr;
441433

442-
tunnel->writeMessage(thr, ac);
434+
tunnel->writeMessage(remap_id[thr], ac);
443435
}
444436

445437
VOID WriteFenceInstructionMarker(UINT32 thr, ADDRINT ip)
@@ -448,7 +440,7 @@ VOID WriteFenceInstructionMarker(UINT32 thr, ADDRINT ip)
448440
ac.command = ARIEL_FENCE_INSTRUCTION;
449441
ac.instPtr = (uint64_t) ip;
450442

451-
tunnel->writeMessage(thr, ac);
443+
tunnel->writeMessage(remap_id[thr], ac);
452444
}
453445

454446
VOID WriteInstructionRead(ADDRINT* address, UINT32 readSize, THREADID thr, ADDRINT ip,
@@ -466,7 +458,7 @@ VOID WriteInstructionRead(ADDRINT* address, UINT32 readSize, THREADID thr, ADDRI
466458
ac.inst.instClass = instClass;
467459
ac.inst.simdElemCount = simdOpWidth;
468460

469-
tunnel->writeMessage(thr, ac);
461+
tunnel->writeMessage(remap_id[thr], ac);
470462
}
471463

472464
VOID WriteInstructionWrite(ADDRINT* address, UINT32 writeSize, THREADID thr, ADDRINT ip,
@@ -498,7 +490,7 @@ VOID WriteInstructionWrite(ADDRINT* address, UINT32 writeSize, THREADID thr, ADD
498490
}
499491
printf("\n");
500492
*/
501-
tunnel->writeMessage(thr, ac);
493+
tunnel->writeMessage(remap_id[thr], ac);
502494
}
503495

504496
VOID WriteStartInstructionMarker(UINT32 thr, ADDRINT ip, UINT32 instClass, UINT32 simdOpWidth)
@@ -508,15 +500,15 @@ VOID WriteStartInstructionMarker(UINT32 thr, ADDRINT ip, UINT32 instClass, UINT3
508500
ac.instPtr = (uint64_t) ip;
509501
ac.inst.simdElemCount = simdOpWidth;
510502
ac.inst.instClass = instClass;
511-
tunnel->writeMessage(thr, ac);
503+
tunnel->writeMessage(remap_id[thr], ac);
512504
}
513505

514506
VOID WriteEndInstructionMarker(UINT32 thr, ADDRINT ip)
515507
{
516508
ArielCommand ac;
517509
ac.command = ARIEL_END_INSTRUCTION;
518510
ac.instPtr = (uint64_t) ip;
519-
tunnel->writeMessage(thr, ac);
511+
tunnel->writeMessage(remap_id[thr], ac);
520512
}
521513

522514
VOID WriteInstructionReadWrite(THREADID thr, ADDRINT* readAddr, UINT32 readSize,
@@ -557,7 +549,7 @@ VOID WriteNoOp(THREADID thr, ADDRINT ip)
557549
ArielCommand ac;
558550
ac.command = ARIEL_NOOP;
559551
ac.instPtr = (uint64_t) ip;
560-
tunnel->writeMessage(thr, ac);
552+
tunnel->writeMessage(remap_id[thr], ac);
561553
}
562554
}
563555
}
@@ -894,7 +886,7 @@ void mapped_ariel_output_stats()
894886
ArielCommand ac;
895887
ac.command = ARIEL_OUTPUT_STATS;
896888
ac.instPtr = (uint64_t) 0;
897-
tunnel->writeMessage(thr, ac);
889+
tunnel->writeMessage(remap_id[thr], ac);
898890
}
899891

900892
// same effect as mapped_ariel_output_stats(), but it also sends a user-defined reference number back
@@ -904,7 +896,7 @@ void mapped_ariel_output_stats_buoy(uint64_t marker)
904896
ArielCommand ac;
905897
ac.command = ARIEL_OUTPUT_STATS;
906898
ac.instPtr = (uint64_t) marker; //user the instruction pointer slot to send the marker number
907-
tunnel->writeMessage(thr, ac);
899+
tunnel->writeMessage(remap_id[thr], ac);
908900
}
909901

910902
void mapped_ariel_flushline(void *virtualAddress)
@@ -926,22 +918,6 @@ void mapped_ariel_fence(void *virtualAddress)
926918
WriteFenceInstructionMarker(thr, ip);
927919
}
928920

929-
/*
930-
void mapped_api_mpi_init() {
931-
api_mpi_init_used = 1;
932-
}
933-
*/
934-
935-
/*
936-
int check_for_api_mpi_init() {
937-
if (!api_mpi_init_used && !getenv("ARIEL_DISABLE_MPI_INIT_CHECK")) {
938-
fprintf(stderr, "Error: fesimple.cc: The Ariel API verion of MPI_Init_{thread} was not used, which can result in errors when used in conjunction with OpenMP. Please link against the Ariel API (included in this distribution at src/sst/elements/ariel/api) or disable this message by setting the environment variable `ARIEL_DISABLE_MPI_INIT_CHECK`\n");
939-
exit(1);
940-
}
941-
return 0;
942-
}
943-
*/
944-
945921
int ariel_mlm_memcpy(void* dest, void* source, size_t size) {
946922
#ifdef ARIEL_DEBUG
947923
fprintf(stderr, "Perform a mlm_memcpy from Ariel from %p to %p length %llu\n",
@@ -974,7 +950,7 @@ int ariel_mlm_memcpy(void* dest, void* source, size_t size) {
974950
ac.dma_start.dest = ariel_dest;
975951
ac.dma_start.len = length;
976952

977-
tunnel->writeMessage(thr, ac);
953+
tunnel->writeMessage(remap_id[thr], ac);
978954

979955
#ifdef ARIEL_DEBUG
980956
fprintf(stderr, "Done with ariel memcpy.\n");
@@ -1002,7 +978,7 @@ void ariel_mlm_set_pool(int new_pool)
1002978
ArielCommand ac;
1003979
ac.command = ARIEL_SWITCH_POOL;
1004980
ac.switchPool.pool = newDefaultPool;
1005-
tunnel->writeMessage(thr, ac);
981+
tunnel->writeMessage(remap_id[thr], ac);
1006982

1007983
// Keep track of the default pool
1008984
default_pool = (UINT32) new_pool;
@@ -1054,7 +1030,7 @@ void* ariel_mmap_mlm(int fileID, size_t size, int level)
10541030
std::cout<<"File ID at FESIMPLE IS : "<<ac.mlm_mmap.fileID<<std::endl;
10551031
std::cout<<"After ******"<<std::endl;
10561032

1057-
tunnel->writeMessage(thr, ac);
1033+
tunnel->writeMessage(remap_id[thr], ac);
10581034

10591035
#ifdef ARIEL_DEBUG
10601036
fprintf(stderr, "%u: Ariel mmap_mlm call allocates data at address: 0x%llx\n",
@@ -1109,7 +1085,7 @@ void* ariel_mlm_malloc(size_t size, int level) {
11091085
ac.mlm_map.alloc_level = allocationLevel;
11101086
}
11111087

1112-
tunnel->writeMessage(thr, ac);
1088+
tunnel->writeMessage(remap_id[thr], ac);
11131089

11141090
#ifdef ARIEL_DEBUG
11151091
fprintf(stderr, "%u: Ariel mlm_malloc call allocates data at address: 0x%llx\n",
@@ -1154,7 +1130,7 @@ void ariel_mlm_free(void* ptr)
11541130
ArielCommand ac;
11551131
ac.command = ARIEL_ISSUE_TLM_FREE;
11561132
ac.mlm_free.vaddr = virtAddr;
1157-
tunnel->writeMessage(thr, ac);
1133+
tunnel->writeMessage(remap_id[thr], ac);
11581134

11591135
} else {
11601136
fprintf(stderr, "ARIEL: Call to free in Ariel did not find a matching local allocation, this memory will be leaked.\n");
@@ -1206,14 +1182,14 @@ VOID ariel_postmalloc_instrument(ADDRINT allocLocation)
12061182
if (toFast[thr].count == 0) {
12071183
toFast[thr].valid = false;
12081184
}
1209-
tunnel->writeMessage(thr, ac);
1185+
tunnel->writeMessage(remap_id[thr], ac);
12101186
}
12111187
} else if (shouldOverride) {
12121188
ac.mlm_map.alloc_level = overridePool;
1213-
tunnel->writeMessage(thr, ac);
1189+
tunnel->writeMessage(remap_id[thr], ac);
12141190
} else if (InterceptMemAllocations.Value()) {
12151191
ac.mlm_map.alloc_level = allocationLevel;
1216-
tunnel->writeMessage(thr, ac);
1192+
tunnel->writeMessage(remap_id[thr], ac);
12171193
}
12181194

12191195
/*printf("ARIEL: Created a malloc of size: %" PRIu64 " in Ariel\n",
@@ -1231,7 +1207,7 @@ VOID ariel_postfree_instrument(ADDRINT allocLocation)
12311207
ArielCommand ac;
12321208
ac.command = ARIEL_ISSUE_TLM_FREE;
12331209
ac.mlm_free.vaddr = virtAddr;
1234-
tunnel->writeMessage(thr, ac);
1210+
tunnel->writeMessage(remap_id[thr], ac);
12351211
}
12361212

12371213
void mapped_ariel_malloc_flag_fortran(int* mallocLocId, int* count, int* level)
@@ -1278,7 +1254,7 @@ void ariel_start_RTL_sim(RTL_shmem_info* rtl_shmem) {
12781254

12791255
THREADID thr = PIN_ThreadId();
12801256
const uint32_t thrID = (uint32_t) thr;
1281-
tunnel->writeMessage(thrID, acRtl);
1257+
tunnel->writeMessage(remap_id[thrID], acRtl);
12821258
#ifdef ARIEL_DEBUG
12831259
fprintf(stderr, "\nMessage to add RTL Event into Ariel Event Queue successfully delivered via ArielTunnel");
12841260
#endif
@@ -1299,7 +1275,7 @@ void ariel_update_RTL_signals(RTL_shmem_info* rtl_shmem) {
12991275

13001276
THREADID thr = PIN_ThreadId();
13011277
const uint32_t thrID = (uint32_t) thr;
1302-
tunnel->writeMessage(thrID, acRtl);
1278+
tunnel->writeMessage(remap_id[thrID], acRtl);
13031279
#ifdef ARIEL_DEBUG
13041280
fprintf(stderr, "\nMessage to add RTL Event into Ariel Event Queue to update RTL signals successfully delivered via ArielTunnel");
13051281
#endif
@@ -1496,29 +1472,12 @@ int main(int argc, char *argv[])
14961472
{
14971473
if (PIN_Init(argc, argv)) return Usage();
14981474

1499-
syscall_id = PIN_CreateThreadDataKey(nullptr);
1500-
if (syscall_id == INVALID_TLS_KEY) {
1501-
std::cerr << "Failed to create thread-local storage key!" << std::endl;
1502-
return 1;
1503-
}
1504-
clone_is_mpi = PIN_CreateThreadDataKey(nullptr);
1505-
if (clone_is_mpi == INVALID_TLS_KEY) {
1506-
std::cerr << "Failed to create thread-local storage key!" << std::endl;
1507-
return 1;
1508-
}
1509-
_os_tid = PIN_CreateThreadDataKey(nullptr);
1510-
if (_os_tid == INVALID_TLS_KEY) {
1511-
std::cerr << "Failed to create thread-local storage key!" << std::endl;
1512-
return 1;
1513-
}
1514-
num_threads = 1;
15151475

15161476

15171477
// Load the symbols ready for us to mangle functions.
15181478
//PIN_InitSymbolsAlt(IFUNC_SYMBOLS);
15191479
PIN_InitSymbols();
15201480
PIN_AddFiniFunction(Fini, 0);
1521-
PIN_AddThreadStartFunction(ThreadStart, nullptr);
15221481
PIN_AddSyscallEntryFunction(SyscallEntry, 0);
15231482

15241483
PIN_InitLock(&mainLock);
@@ -1560,9 +1519,7 @@ int main(int argc, char *argv[])
15601519

15611520
core_count = MaxCoreCount.Value();
15621521

1563-
remap_id[0] = 0;
1564-
next_app_thread = 1;
1565-
next_mpi_thread = core_count;
1522+
init_remapping_data(core_count);
15661523

15671524
instrument_instructions = InstrumentInstructions.Value();
15681525

0 commit comments

Comments
 (0)