我的应用场景是这样的:我想评估在四核机器上处理相同数据量时可以获得的性能提升。我有以下两个配置:
i)1进程:一个没有任何线程的程序,从1M到1G处理数据,假设系统只运行其4核中的一个。
ii)4线程进程:一个带有4个线程(所有线程执行相同的操作),但只处理25%的输入数据的程序。
在我的程序中创建4个线程时,我使用了pthread的默认选项(即没有特定的pthread_attr_t)。我认为与1进程配置相比,4线程配置的性能增益应该更接近400%(或在350%和400%之间)。
我像下面这样分别记录了创建线程所需的时间:
timer_start(&threadCreationTimer);
pthread_create( &thread0, NULL, fun0, NULL );
pthread_create( &thread1, NULL, fun1, NULL );
pthread_create( &thread2, NULL, fun2, NULL );
pthread_create( &thread3, NULL, fun3, NULL );
threadCreationTime = timer_stop(&threadCreationTimer);
pthread_join(&thread0, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
pthread_join(&thread3, NULL);
由于输入数据的增加可能会导致每个线程所需的内存增加,因此提前加载所有数据绝对不是可行的选择。因此,为了确保不增加每个线程的内存要求,每个线程按小块读取数据,处理它并读取下一块进行处理,以此类推。因此,我的线程运行的函数的代码结构如下:
timer_start(&threadTimer[i]);
while(!dataFinished[i])
{
threadTime[i] += timer_stop(&threadTimer[i]);
data_source();
timer_start(&threadTimer[i]);
process();
}
threadTime[i] += timer_stop(&threadTimer[i]);
当进程接收并处理了所有需要的数据时,变量dataFinished[i]
被标记为true
。 Process()
知道何时执行这个操作 :-)
在主函数中,我计算了4线程配置所需的时间:
execTime4Thread = max(threadTime[0], threadTime[1], threadTime[2], threadTime[3]) + threadCreationTime
.
性能提升可以通过以下公式简单计算:
gain = execTime1process / execTime4Thread * 100
问题: 对于小数据大小(大约1M到4M),性能提升通常很好(在350%到400%之间)。然而,随着输入大小的增加,性能提升的趋势呈指数级下降。它一直下降,直到某些数据大小达到50M左右,然后稳定在200%左右。一旦达到这个点,即使是1GB的数据,它也保持几乎稳定。
我的问题是,有人能否建议这种行为的主要原因(即开始时性能下降但后来保持稳定)?
还有建议如何解决这个问题?
值得一提的是,我还调查了每个线程的threadCreationTime
和threadTime
的行为,以了解发生了什么。对于1M的数据,这些变量的值很小,但随着数据大小的增加,这两个变量都呈指数级增加(但是threadCreationTime
应该保持几乎不变,而threadTime
应该以处理数据的速度相应地增加)。继续增加直到50M左右,threadCreationTime
变得稳定,threadTime
(就像性能下降一样)也变得稳定,而threadCreationTime
则以与要处理的数据增加相对应的恒定速率增加(这被认为是可以理解的)。
您认为增加每个线程的堆栈大小、进程优先级或自定义其他参数类型的调度程序的值(使用pthread_attr_init
)可以有所帮助吗?
PS: 在Linux的故障安全模式下以root身份运行程序时获得结果(即最小化OS运行而没有GUI和网络设置)。