我很想知道如何编写Intel x86程序集上的并发软件.带有屈服的线程或协同程序都很有趣.
我意识到这在组装中不切实际,但我只是好奇.
现代CPU拥有相当多的性能指标 - http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming- manual-325384.html如何阅读它们?我对缓存未命中和分支错误预测感兴趣.
在查看英特尔数字随机数发生器(DRNG)软件实施指南之后,我对RDRAND调用时生成器的内部状态会发生什么问题提出了一些问题.不幸的是,答案似乎不在指南中.
根据该指南,在DRNG内部有四个128位缓冲器,用于提供随机位以RDRAND进行漏极.RDRAND本身将提供16位,32位或64位随机数据,具体取决于目标寄存器的宽度:
rdrand ax ; put 16 random bits in ax
rdrand eax ; put 32 random bits in eax
rdrand rax ; put 64 random bits in rax
Run Code Online (Sandbox Code Playgroud)
使用更大的目标寄存器会更快地清空这些128位缓冲区吗?例如,如果我只需要2位随机性,那么我是否应该经历在64位寄存器上使用16位寄存器的麻烦?这会对DRNG的吞吐量产生任何影响吗?我想避免消耗比必要更多的随机性.
指南说执行后将设置进位标志RDRAND:
CF = 1 Destination register valid. Non-zero random value
available at time of execution. Result placed in register.
CF = 0 Destination register all zeros. Random value not available
at time of execution. May be retried.
Run Code Online (Sandbox Code Playgroud)
"不可用"是什么意思?随机数据是否可用,因为RDRAND调用过快地耗尽了这些128位缓冲区?或者不可用意味着DRNG未通过健康检查而无法生成任何新数据?基本上,我试图理解CF …
在英特尔64和IA-32架构软件开发人员手册说,大约由单一处理器的行动("在P6更多最近的处理器系列内存排序和"第8.2.2节)重新排序如下:
读取可以使用较旧的写入到不同位置进行重新排序,但不能使用较旧的写入到同一位置.
接下来讨论与早期处理器相比放松的点时,它说:
存储缓冲区转发,当读取将写入传递到同一存储器位置时.
据我所知,"存储缓冲区转发"并未在任何地方精确定义(也不是"通过").读取将写入传递到同一位置是什么意思,因为上面说它不能通过写入同一位置来重新排序?
在英特尔内部网络应用程序中,从Sandy Bridge到Haswell的几项操作似乎已经恶化.例如,许多插入操作(如_mm256_insertf128_si256)显示如下的成本表:
Performance
Architecture Latency Throughput
Haswell 3 -
Ivy Bridge 1 -
Sandy Bridge 1 -
Run Code Online (Sandbox Code Playgroud)
我发现这种差异令人费解.这有什么不同,因为有新的指令可以取代这些或补偿它的东西(哪些)?有谁知道Skylake是否进一步改变了这个模型?
我们有一个简单的内存吞吐量基准.对于大块内存,它所做的只是重复记忆.
在几台不同的机器上查看结果(针对64位编译),Skylake机器的性能明显优于Broadwell-E,保持OS(Win10-64),处理器速度和RAM速度(DDR4-2133)不变.我们不是说几个百分点,而是大约2个因素.Skylake配置为双通道,Broadwell-E的结果不会因双/三/四通道而异.
任何想法为什么会这样?随后的代码在VS2015的Release中编译,并报告完成每个memcpy的平均时间:
64位:Skylake为2.2ms,Broadwell-E为4.5ms
32位:Skylake为2.2ms,Broadwell-E为3.5ms.
通过利用多个线程,我们可以在四通道Broadwell-E构建上获得更大的内存吞吐量,这很不错,但是看到单线程内存访问的这种巨大差异令人沮丧.为什么差异如此显着的任何想法?
我们还使用了各种基准测试软件,他们验证了这个简单示例所展示的内容 - 单线程内存吞吐量在Skylake上更好.
#include <memory>
#include <Windows.h>
#include <iostream>
//Prevent the memcpy from being optimized out of the for loop
_declspec(noinline) void MemoryCopy(void *destinationMemoryBlock, void *sourceMemoryBlock, size_t size)
{
memcpy(destinationMemoryBlock, sourceMemoryBlock, size);
}
int main()
{
const int SIZE_OF_BLOCKS = 25000000;
const int NUMBER_ITERATIONS = 100;
void* sourceMemoryBlock = malloc(SIZE_OF_BLOCKS);
void* destinationMemoryBlock = malloc(SIZE_OF_BLOCKS);
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
while (true)
{
LONGLONG total = 0;
LONGLONG max = 0;
LARGE_INTEGER StartingTime, …Run Code Online (Sandbox Code Playgroud) 有人可以解释英特尔内部指南中给出的延迟和吞吐量值吗?
我是否正确理解延迟是指令运行所需的时间单位,吞吐量是每个时间单位可以启动的指令数量?
如果我的定义是正确的,为什么某些指令的延迟在较新的CPU版本上更高(例如mulps)?
intel ×10
x86 ×4
assembly ×3
c++ ×2
concurrency ×2
performance ×2
x86-64 ×2
avx2 ×1
avx512 ×1
benchmarking ×1
c ×1
cpu ×1
intrinsics ×1
memory-model ×1
optimization ×1
rdrand ×1
simd ×1
sse ×1
std ×1
stl ×1
tbb ×1