超执行绪(英语:Hyper-Threading,缩写HT[1]英特尔专有的同时多执行绪技术,于2002年发布,用来改进x86微处理器执行平行计算(一次执行多个任务)的能力。超执行绪技术原先只应用于英特尔 Xeon 处理器中,当时称为“Super-Threading”。之后陆续应用在Pentium 4 HT中,早期代号为Jackson。

在 HTT 的高级描述中,指令从 RAM 中获取(不同颜色的框代表四个不同进程的指令),由前端解码和重新排序(白色框代表流水线),然后传递给能够执行在同一时钟周期内执行来自两个不同程序的指令。
在 HTT 的高级描述中,指令从 RAM 中获取(不同颜色的框代表四个不同进程的指令),由前端解码和重新排序(白色框代表流水线),然后传递给能够执行在同一时钟周期内执行来自两个不同程序的指令。

通过此技术,英特尔实现在一个实体CPU中,提供两个逻辑线程。之后的Pentium D虽不支援超执行绪技术,但集成了两个实体核心,所以仍会见到两个线程。超执行绪的未来发展,是提升处理器的逻辑线程。英特尔于2016年发布的Core i7-6950X便是将10核心的处理器,加上超执行绪技术,使之成为20个逻辑线程的产品。

英特尔表示,超执行绪技术让Pentium 4 HT处理器增加5%的裸晶面积,就可以换来15%~30%的效能提升。但实际上,在某些程式或未对多执行绪编译的程式而言,超执行绪反而会降低效能。除此之外,超执行绪技术亦要作业系统的配合,普通支援多处理器技术的系统亦未必能充分发挥该技术。例如Windows 2000,英特尔并不鼓励使用者在此系统中利用超执行绪。原先不支援多核心的Windows XP Home Edition却支援超执行绪技术。

运作方式

编辑

每个单位时间内,一个单执行管线的CPU只能处理一个执行绪作业系统:thread),以这样的单位进行,如果想要在一单位时间内处理超过一个执行绪是不可能的,除非是有两个CPU的实体单元。双核心技术是将两个一样的CPU放置于一个封装内(或直接将两个CPU做成一个晶片),而英特尔的HT技术是在CPU内部仅复制必要的资源、让两个执行绪可同时执行;在一单位时间内处理两个执行绪的工作,模拟实体双核心、双执行绪运作。

Intel自Pentium开始引入超纯量乱序执行、大量的暂存器寄存器重命名、多指令解码器预测执行等特性;这些特性的原理是让CPU拥有大量资源,并可以预先执行及平行执行指令,以增加指令执行效率,可是在现实中这些资源经常闲置;为了有效利用这些资源,就干脆再增加一些资源来执行第二个执行绪,让这些闲置资源可执行另一个执行绪,而且CPU只要增加少数资源就可以模拟成两个执行绪运作。

P4处理器需多加一个Logical CPU Pointer(逻辑处理单元)。因此P4 HT的die的面积比以往的P4增大了5%。而其馀部分如ALU(整数运算单元)、FPU(浮点运算单元)、L2 Cache(二级快取)并未增加,且是共享的。

使用HT技术的CPU

编辑
 
编号SL6WK支援HT的P4 3.0G
 
虚拟的2个CPU在工作管理员中显示出都在运转

Pentium 4 CPU中,Northwood及其之后推出的版本内建超执行绪技术;而双核心的Pentium D中也只有EE版提供HT技术。英特尔的Core 2处理器则没有HT技术。[2]

而在2008年推出的Intel Core i7处理器又支援HT技术,在Nehalem微架构中,Hyper-Threading大举卷土重来。Intel的Hyper-Threading(又称同步多线程)是善用执行绪平行性的方法,让单一核心在应用软体层能执行两个逻辑线程。超线程技术在部分型号Intel Core i3/i5/i7/i9处理器中可用。从Kaby Lake Pentium开始,定位低阶的Pentium(部分型号)也支援超执行绪技术。

顾虑

编辑

把执行管线的状态,想像成流水线,资源A→资源B→资源C,来了两条资料要计算,一条需要消耗A的100%→B的50%→C的50%,另一条一样需要消耗A的100%→B的50%→C的50%,一条单纯的(无HT)的执行管线的资源A需要先运用100%效能把第一条运算完才能再运算下一条,但后面的资源B跟C却都有50%效能的浪费;如果把执行管线的资源A,变成两个,资源B跟C依然只有一个,那这条管线就可以变成“两个资源A同时消耗100%效能运算两条资料,到了资源B跟C阶段时,两条资料再各自消耗50%的效能”,即达成“不必增加一条完整的执行管线,却能在一样时间运算两条执行绪”。

但实际应用时,执行管线不会都是收到这么完美的需运算资料,可能会是需消耗“A的10%→B的70%→C的70%”+“A的30%→B的50%→C的70%”+......等多种不同效能需求的需运算资料,依照文件的统计数字,整体能够提升的效能约为5~15%左右,且万一发生资源互抢的情形时,整体效能反而会下降。

要令电脑支持超执行绪技术,通常需作业系统和硬体的配合。晶片组需要支援具有HT技术之处理器。为此,当时的Intel推出了新的晶片组,i865PE和i875P。要充分发挥超执行绪的效能,使用者要使用Windows 2000之后的作业系统,而Windows XP家用版亦支援超执行绪技术。除了微软的Windows外,Linux kernel 2.4.x亦开始支援该技术。软体方面,通常优化多执行绪的程式都可以支援到。早期,游戏软体的支援是比较少。但随著多核心技术的普及,愈来愈多游戏软体支援多执行绪的处理器。[3]

安全

编辑

2005 年 5 月,Colin Percival 演示了 Pentium 4 上的超线程可以使用基于时间的侧信道攻击来监控与其共享缓存的另一个线程的内存访问模式,从而窃取密码信息。 这实际上不是计时攻击,因为恶意线程只测量自己执行的时间。 对此的潜在解决方案包括处理器更改其缓存逐出策略或操作系统阻止在同一物理内核上同时执行具有不同权限的线程。2018 年,OpenBSD 操作系统禁用了超线程,以避免数据可能从应用程序泄漏到其他软件,原因是 Foreshadow/L1TF 漏洞。2019 年,一系列漏洞导致安全专家建议在所有设备上禁用超线程。

示例:获取物理核心数与逻辑核心数

编辑

Windows API的GetLogicalProcessorInformation可获取当前计算机的物理核心数逻辑核心数:

DWORD GetProcessorCoreCount(DWORD &PhysicalProcessorCoreCount,DWORD &LogicalProcessorCoreCount )
{
	typedef BOOL(WINAPI *LPFN_GLPI)(
		PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
		PDWORD);

	LPFN_GLPI glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");

	if (NULL == glpi)
		return 0;

	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
	DWORD returnLength = 0;
	 PhysicalProcessorCoreCount = 0;
	 LogicalProcessorCoreCount = 0;
	while (true)
	{
		DWORD rc = glpi(buffer, &returnLength);

		if (FALSE == rc)
		{
			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
			{
				if (buffer)
					free(buffer);

				buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
					returnLength);

				if (NULL == buffer)
					return 0;
			}
			else
			{
				return 0;
			}
		}
		else
		{
			break;
		}
	}

	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer;

	DWORD byteOffset = 0;
	while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
	{
		switch (ptr->Relationship)
		{
		case RelationProcessorCore:
		{
			++PhysicalProcessorCoreCount;

			// count the logical processor, which is equal the count of digital 1's of ptr->ProcessorMask
			ULONG_PTR   ProcessorMask = ptr->ProcessorMask;
			while (ProcessorMask != 0)
			{
				ProcessorMask &= ProcessorMask - 1;
				LogicalProcessorCoreCount++;
			}
			break;
		}
		default:
			break;
		}
		byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
		++ptr;
	}
	free(buffer);
	return -1;
}

上述程式码在32位编译时最多能枚举32个逻辑核心,在64位编译时最多枚举64个逻辑核心。如果超过64,应该使用 processor group.

另见

编辑

注脚

编辑

外部链接

编辑