单核CPU,多线程与性能<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
问题概述
单核CPU的计算机上, 多线程能够提高程序运行的性能吗? 这个问题看起来简单,实际很复杂,设计到多方面的因素. 首先我们要把概念搞清楚, 那就是什么是性能? 一般来说, 我们把运行一个任务所花的时间来评价性能, 所花的时间可以是在CPU上, 也可能是在I/O操作上, 运行任务的程序, 也可能同时在运行另外若干的任务(吞吐量). 这里我们把概念给缩小一下:
我们这里把性能限制在一个程序运行一个任务, 这个任务是只消耗CPU资源(CPU bound), 所花的时间越小, 说明性能越好. 为了纯粹地说明问题, 我们排除了数据共享问题, 即线程之间不做任何同步动作, 完全隔离.
从理论上说,如果计算机只执行这一个测试程序, 那么单线程要比多线程性能好,因为多线程需要做线程上下文环境的切换; 而当计算机同时运行其他的进程, 假设其他进程里也有多个大量消耗CPU的任务, 那么我们的程序由于是多线程, 抢到CPU时间片的机会增多, 它的性能应该好于单线程.
理论上是这么回事, 但我们知道, 实践与理论是有差距的, 我们的测试不可能在真空环境中. 操作系统的实现有高度的戏剧性, 谁也不能预测实际的测试一定与理论相符, 另外在我们实际的运行环境中,各种情况导致的系统差异很大, 因为我们必须做一些测试.
MSDN上有一篇著名的文章<<Win32 Multithreading Performance>>, 里面讲的东西与我们很相近. 它主要论述的是串行计算和并行计算的性能比较, 我们直接拿它的例子, 进行一些更改, 来测试我们的假设.
首先讨论我们测试的主题与它的不同, 主要有2点: 1, 我们讨论的任务是一个固定的任务, 而它里面讨论的是数个计算量不同的任务, 而计算不同的任务涉及到吞吐量的概念; 2, 我们讨论的是线程数量之间的比较(分别测试不同数量的线程), 而它只有单线程与多线程的比较.
图1: 多个不同的任务并行处理
图案2: 一个固定的任务并行处理
测试程序介绍
一个任务在这里简化为一个持续占用CPU的计算, 为了测试的准确性, 中间不可以有任何的I/O操作, 例如:
for (int iCounter=0; iCounter<iLoopCount; iCounter++);
给定的任务量iDelay,单位是毫秒, 有一段模拟的代码, 从而把一秒的时间转换为循环数iLoopCount.里面所用的两个API是QueryPerformanceFrequency和QueryPerformanceCounter.
我们增加一个方法来取代OnWorstcase:
void CThreadlibtestView::OnFixTask()
{
if(!m_iNumberOfThreads)
{
MessageBeep(-1);
return;
};
for (int iLoop=0;iLoop<m_iNumberOfThreads;iLoop++)
{
m_iNumbers[iLoop]=(int)&m_tbConc[iLoop];
m_tbConc[iLoop].iId=iLoop;
if(iLoop==0)
m_tbConc[iLoop].iDelay=m_iDelay/m_iNumberOfThreads+m_iDelay%m_iNumberOfThreads;
else
m_tbConc[iLoop].iDelay=m_iDelay/m_iNumberOfThreads;
m_tbConc[iLoop].tbOutputTarget=this;
m_tbConc[iLoop].iStartOrder=0;
m_tbConc[iLoop].iEndOrder=0;
m_tbConc[iLoop].iTouchCount=0;
};
}
另外我们指定特定的任务量和线程数量:
int iTaskSize[]={100,500,1000,2000,4000};
int iThreadSize[]={2,5,10,15,20};
单线程时候我们调用OnSerial(), 多线程时调用OnConcurrent(), 线程数量分别取iThreadSize里的值.
测试次数仍然保持10次, 取平均值, 整个测试我们分别运行两次, 第一次在负载很轻的计算机上运行, 第二次在同样的计算机上加载一个大负载的进程, 此进程里有十个线程, 每个线程都是基于CPU的密集计算, 程序如下:
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
DWORD busyTime=10;
while(true)
{
DWORD startTime=GetTickCount();
for(;GetTickCount()-startTime<=busyTime;)
;
Sleep(1);
}
return 0;
}
特别要注意的是, 两次计算不能各启动一个进程, 必须在一个进程中, 因为在程序开始,我们会算出1秒对应循环数, 而每次启动程序这个数字是不同的, 为了更有意义的比较,我们要求这个数字一定相同.
测试环境: CPU Intel Pentium M 1.7 G; 1047472KB RAM, Windows 2000 professional SP4.
一秒的循环数:146278208
测试结果
图3: 在负载轻的系统上测试结果
图4: 在负载重的系统上测试结果
结论和建议
根据测试结果,我们可以得出一些结论(针对单核CPU):
在负载轻的系统上, 多线程不适合处理基于CPU的任务,而在负载重的系统上,多线程可以帮助提高性能.
这是一个模糊和慎重的结论, 因为测试结果里的一些现象我也给不出合适的理由, 应该属于操作系统”戏剧化”和”不确定性”的表现吧(操作系统会对某些线程动态提高优先级,但本例中的线程优先级保持不变.), 例如在负载轻的机器上, 20个线程和2个线程运行时间差异不大; 在负载重的机器上, 2个线程运行时间比单线程还长, 而当线程数量增加到5时, 性能才有显著的提高.
所以我的建议是,在单核CPU机器上,处理CPU密集的任务时, 不推荐使用多线程, 除非你对目标机器非常的了解和确定,并经过严格的测试. 当然, 涉及到其他I/O操作的任务, 比如等待用户按键, 读取文件, 网络通讯等, 多线程才是正当其选的解决方案.
分享到:
相关推荐
在计算机科学领域,多核...理解单线程与多线程的特点,以及如何有效地管理线程同步,是提升软件性能和可靠性的关键。在实际开发中,应根据具体需求选择合适的线程模型,并利用适当的同步机制确保程序的正确性和高效性。
多核技术的优点在于可以在物理层面提供并行性,因此它对于多线程和多任务的处理能力比单核CPU要强得多。 通过生活中的高速公路和收费站模型,我们可以更加直观地理解这些概念。简单CPU就像单车道马路加单收费闸口,...
然后,使用SPEC CPU2017工具对Hi1616和Intel E5-2650v4进行了比较,分别从不同线程数下的计算速度性能和不同任务拷贝数下的吞吐量性能两个方面进行了比较。 实验结果显示,在多任务高并发计算场景下,Hi1616更具有...
制造商可能会发布更新来优化CPU性能,包括改善多线程支持。 2. **禁用超线程**:某些CPU支持超线程技术,这使单核CPU模拟出多个逻辑核心。如果你的CPU不支持超线程,确保它未被错误地开启。在BIOS设置中,查找...
在IT领域,多线程编程是一项关键技能,尤其是在性能优化和并发处理方面。本文将深入探讨多线程编程的基础知识,以帮助初学者快速入门。 首先,我们需要理解什么是多线程。多线程是指在一个进程中同时执行多个独立的...
然而,由于大多数计算机为单核CPU,线程实际上是通过时间片轮转的方式交替执行,看起来是并行的。过多的线程竞争CPU可能导致频繁的线程切换,反而降低系统性能。 **四、Win32 API与MFC多线程支持** Win32 API提供了...
在单核CPU系统中,操作系统通过时间片轮转的方式模拟多线程并行执行;而在多核或多处理器系统中,线程可以真正地并行运行,显著提升程序性能。 二、Delphi中的线程类 Delphi中主要使用TThread类来创建和管理线程。...
多线程与多核编程是现代计算机系统中提高性能和响应速度的重要技术。在多任务环境中,操作系统通过多线程实现并发执行,使得用户能够同时处理多个任务,从而提升用户体验。而多核CPU则提供了硬件层面的并行计算能力...
然而,随着单核处理器性能的提升逐渐达到物理极限,单线程性能增长已经趋向停滞,这就需要软件开发者寻找新的途径来提升性能,而多核处理器和多线程编程就是其中的重要方式。 SIMD技术则是一种处理器指令集架构,它...
### 多线程与多核编程 #### 13.1 进程与线程 **13.1.1 进程与多任务** 进程是操作系统中的一个重要概念,指的是正在执行中的程序。在现代多任务操作系统中,可以同时运行多个程序。进程包含了程序在内存中的所有...
补充概念中,单核CPU一次只能处理一个线程,而多核CPU可以同时处理多个线程,理论上性能是成比例增加的。例如,一个四核的CPU在理想情况下,性能应该是单核的四倍。然而,实际性能提升受到诸多因素影响,如任务的...
在单核CPU中,多线程通过时间片轮转实现并发,而在多核CPU中,不同线程可以真正地并行执行。多线程编程可以提高程序的响应速度和系统资源的利用率,尤其是在执行I/O密集型或计算密集型任务时。 多线程的实现通常有...
多线程在单核CPU中实现并发,在多核CPU中可实现并行。 二、多线程的实现 1. 线程创建:在Java中,可以通过继承`Thread`类或实现`Runnable`接口来创建线程。Python中,可以使用`threading`模块的`Thread`类。 2. ...
CPU测试旨在衡量处理器的计算能力,包括整数运算、浮点运算以及多线程处理等性能;内存测试则关注内存的读写速度、带宽和延迟,这些指标直接影响到系统运行大型应用或处理大量数据时的响应速度。 ubench的安装过程...
文档指出,多线程通过并行处理可以在同一时间内完成多项任务,减少单个任务占用CPU时间,但同时也提到在单核CPU的计算机上,多线程实际上是通过时间分片(时间片轮转)来实现的。因此,如果线程频繁地被切换,反而...
在单核CPU系统中,多线程是通过时间片轮转的方式实现的,系统会快速切换线程的执行状态,给人一种同时运行的错觉。而在多核CPU系统中,不同线程可以真正地并行执行,进一步提升效率。线程间可以通过共享内存进行通信...
在单核CPU时代,多线程主要是为了提高程序响应性,避免长时间阻塞主线程导致用户界面冻结。随着多核CPU的普及,多线程成为充分利用硬件资源、提高系统并发处理能力的有效手段。这部分可能会讨论到线程与进程的区别,...
总结来说,Java多线程技术是实现并发和优化程序性能的重要手段,理解线程的生命周期、创建方式、同步机制以及异常处理,是成为一名合格的Java开发者的必备技能。通过合理地设计和使用多线程,开发者可以构建出高效、...
在单核CPU中,虽然物理上无法同时执行多个线程,但通过快速切换,给人以并发执行的错觉。在多核CPU中,多线程则可以真正实现并行处理,提高程序运行效率。 在iOS开发中,我们常见的多线程实现方式有以下几种: 1. ...