我正在使用 Intel Pin 动态检测多线程程序以进行一些数据竞争检测。我检测内存读/写指令以在运行时收集内存跟踪,然后分析日志。跟踪收集很简单,它在运行时将内存跟踪(包括时间、线程 id、地址等)存储到缓冲区并在最后将其写入。
VOID PIN_FAST_ANALYSIS_CALL RecordMemRead(unsigned int ip, unsigned int addr, THREADID tid){
PIN_GetLock(&lock,tid+1);
membuf[instCounter].tid = tid;
membuf[instCounter].ip = ip;
membuf[instCounter].addr = addr;
membuf[instCounter].op = 'R';
instCounter++;
PIN_ReleaseLock(&lock);
}
VOID PIN_FAST_ANALYSIS_CALL RecordMemWrite(unsigned int ip, unsigned int addr, THREADID tid){
// similar to RecordMemRead()
}
VOID Instruction(INS ins, VOID *v){
if(INS_IsBranchOrCall(ins))
return;
if(INS_IsStackRead(ins))
return;
if(INS_IsStackWrite(ins))
return;
if (INS_IsMemoryRead(ins)){
INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_MEMORYREAD_EA,
IARG_THREAD_ID, IARG_END);
}
else if(INS_IsMemoryWrite(ins)){
INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_MEMORYWRITE_EA,
IARG_THREAD_ID, IARG_END);
}
}
我的麻烦是严重的运行时开销(200x - 500x)。根据其他作品,跟踪收集应该只引入不到 100 倍的开销。我试图通过跳过对堆栈的访问来优化它,但这并没有太大帮助。由于我的仪器是在指令粒度上进行的,因此会记录大量访问。因此,我认为减少运行时开销的唯一方法是减少要收集的访问,也就是只记录对线程之间共享变量(与竞争相关的变量)的访问。
我可以通过某种方式找出对 Pin 中共享变量的访问吗?还是有其他方法可以减少运行时开销?