我做了一个模拟我们服务器代码中发生的事情的实验,我启动了1024个线程,每个线程执行一次系统调用,这需要大约2.8秒才能在我的机器上完成执行。然后我在每个线程的函数中添加usleep(1000000),执行时间增加到16s,当我第二次运行相同的程序时,时间将减少到8s。我想这可能是由cpu cache和cpu context switch引起的,但我不太清楚如何解释它。
此外,避免这种情况发生的最佳做法是什么(增加每个线程的运行时间会导致整个程序性能下降)。
我在这里附上了测试代码,非常感谢您的帮助。
//largetest.cc
#include "local.h"
#include <time.h>
#include <thread>
#include <string>
#include "unistd.h"
using namespace std;
#define BILLION 1000000000L
int main()
{
struct timespec start, end;
double diff;
clock_gettime(CLOCK_REALTIME, &start);
int i = 0;
int reqNum = 1024;
for (i = 0; i < reqNum; i++)
{
string command = string("echo abc");
thread{localTaskStart, command}.detach();
}
while (1)
{
if ((localFinishNum) == reqNum)
{
break;
}
else
{
usleep(1000000);
}
printf("curr num %d\n", localFinishNum);
}
clock_gettime(CLOCK_REALTIME, &end); /* mark the end time */
diff = (end.tv_sec - start.tv_sec) * 1.0 + (end.tv_nsec - start.tv_nsec) * 1.0 / BILLION;
printf("debug for running time = (%lf) second\n", diff);
return 0;
}
//local.cc
#include "time.h"
#include "stdlib.h"
#include "stdio.h"
#include "local.h"
#include "unistd.h"
#include <string>
#include <mutex>
using namespace std;
mutex testNotifiedNumMtx;
int localFinishNum = 0;
int localTaskStart(string batchPath)
{
char command[200];
sprintf(command, "%s", batchPath.data());
usleep(1000000);
system(command);
testNotifiedNumMtx.lock();
localFinishNum++;
testNotifiedNumMtx.unlock();
return 0;
}
//local.h
#ifndef local_h
#define local_h
#include <string>
using namespace std;
int localTaskStart( string batchPath);
extern int localFinishNum;
#endif
答案 0 :(得分:0)
localFinishNum
的读取也应受互斥保护,否则结果将根据线程的调度位置(即哪些内核),缓存何时以及如何失效而无法预测等等。
实际上,如果编译器决定将localFinishNum
放入寄存器(而不是始终从内存中加载),那么如果以优化模式编译它,程序甚至可能不会终止。