Tag: cpu architecture

与单个进程方案相比,多进程方案中的访问时间意外较低

我从program1访问共享库(共享数组数据结构),并找到访问该时间来读取该数组的所有元素。 我得到大约17000个滴答,而只有Program1单独执行。 现在,当我首先在另一个选项卡中执行program2(具有空的while循环以保持终止)时,然后运行program1并测量访问时间以读取该数组的所有元素。 令我惊讶的是,与之前只有Program1执行的情况相比,我获得了8000ticks。 看起来只有program1执行时才需要花费更多时间来读取数组,而有2个程序时,program1正在执行与之前相同的任务,而program2通过while循环保持CPU忙。 预计存在program1的访问时间会更长,而实际结果则相反。 为什么会这样? 这是共享库 #include static const int DATA[1024]={1 ,2 ,3,…..1024]; inline void foo(void) { int j, k=0,count=0; for(j=0;j<1024;j++) { k=DATA[j]; } k+=0; } PROGRAM1 int main(void) { foo(); start=timer(); foo(); end=timer(); printf(“Time1=%llu\n”,end-start); start=timer(); foo(); end=timer(); printf(“Time2=%llu\n”,end-start); start=timer(); foo(); end=timer(); printf(“Time3=%llu\n”,end-start); sleep(1); start=timer(); foo(); end=timer(); printf(“after sleep(1)\n”); printf(“Time4=%llu\n”,end-start); start=timer(); foo(); end=timer(); […]

GCC最高指令集与多种架构兼容

我在由具有不同体系结构的计算机组成的集群上运行作业: gcc -march=native -Q –help=target | grep — ‘-march=’ | cut -f3 gcc -march=native -Q –help=target | grep — ‘-march=’ | cut -f3 gcc -march=native -Q –help=target | grep — ‘-march=’ | cut -f3给我其中一个: broadwell , haswell , ivybridge , sandybridge或skylake 。 可执行文件需要是相同的,所以我不能使用-march=native但同时架构有共同点(我认为它们都支持AVX?)。 我知道gcc (与Intel icc相反)不允许在单个可执行文件中存在多个目标。 我想知道的是,是否有办法向gcc询问与上面列出的所有架构兼容的最高指令集。 gcc版本:8.1.1

如何在Windows / Linux C上检查CPU名称,型号,速度?

我想获得一些关于硬件的C信息: 我有多少CPU 每个核心有多少个核心 每个CPU中每个核心有多少个逻辑核心 CPU名称+型号 CPU速度+频率 CPU架构(x86,x64) 我知道在类似Linux的操作系统上我可以解析/proc/cpuinfo但由于它不是普通文件,我认为它不安全。 在SO上看到这个答案,但它并没有给我我需要的每一个信息。 我应该调用cat /proc/cpuinfo > file.txt然后解析file.txt吗? 我知道cpuid.h (我正在使用GCC)但是找不到关于这个标题的任何文档(无论如何 – 使用它是个好主意吗?)

cpu cacheline和prefetch策略

我读了这篇文章http://igoro.com/archive/gallery-of-processor-cache-effects/ 。 文章说因为缓存行延迟,代码: int[] arr = new int[64 * 1024 * 1024]; // Loop 1 for (int i = 0; i < arr.Length; i++) arr[i] *= 3; // Loop 2 for (int i = 0; i < arr.Length; i += 16) arr[i] *= 3; 将几乎有相同的执行时间,我写了一些示例c代码来测试它。 我使用Ubuntu 64位运行Xeon(R)E3-1230 V2上的代码,使用Debian运行ARMv6兼容处理器rev 7,并在Core 2 T6600上运行它。 所有结果都不是文章所说的。 我的代码如下: long int […]

检测目标CPU上的对齐内存要求

我目前正在尝试构建一个代码,该代码可用于各种机器,从手持式口袋和传感器到数据中心的大型服务器。 这些体系结构之间的(许多)差异之一是对齐内存访问的要求。 “标准”x86 CPU不需要对齐的内存访问,但是如果不遵守规则,许多其他CPU需要它并产生exception。 到目前为止,我一直在使用packed属性(或pragma)强制编译器对已知存在风险的特定数据访问保持谨慎。 它工作正常。 问题是,编译器非常谨慎,以至于在此过程中会丢失大量性能。 由于性能很重要,我们最好重写代码的某些部分以专门处理严格对齐的cpus。 另一方面,这样的代码在cpus上会更慢,它支持未对齐的内存访问(例如x86),因此我们只想在需要严格对齐内存访问的cpus上使用它。 现在的问题是:如何在编译时检测目标架构是否需要严格对齐的内存访问? (或反过来)

您如何从用户模式代码中一般性地检测缓存行关联性?

我正在为valgrind中的cachegrind / callgrind工具编写一个小补丁,它将使用完全通用的代码,CPU指令和缓存配置自动检测(现在只有x86 / x64自动配置,而其他架构不提供CPUID类型配置为非特权代码)。 此代码需要完全在非特权上下文中执行,即纯用户模式代码。 它还需要可以在非常不同的POSIX实现中移植,因此grokking / proc / cpuinfo不会这样做,因为我们的目标系统之一没有这样的东西。 检测CPU的频率,高速缓存的数量,它们的大小,甚至高速缓存行大小都可以使用100%通用POSIX代码完成,该代码没有任何特定于CPU的操作码(只是很多合理的假设,例如添加两个数字在一起,如果没有内存或寄存器依赖性停顿,可能会在一个周期内执行)。 这部分相当简单。 什么不是那么简单,为什么我问StackOverflow,是如何检测给定缓存的缓存行关联性? 关联性是缓存中可以包含来自主内存的给定缓存行的位数。 我可以看到可以检测到L1缓存关联,但L2缓存? 当然L1关联性会受到影响吗? 我很欣赏这可能是一个无法解决的问题。 但我把它扔到StackOverflow上,希望有人知道我不知道的事情。 请注意,如果我们在这里失败,我将简单地在四方的关联性默认值中进行硬编码,假设它不会对结果产生巨大影响。 谢谢, 尼尔

CLFLUSH如何处理尚未缓存的地址?

我们正在尝试使用Intel CLFLUSH指令在用户空间中刷新Linux中进程的缓存内容。 我们创建了一个非常简单的C程序,它首先访问一个大型数组,然后调用CLFLUSH来刷新整个数组的虚拟地址空间。 我们测量CLFLUSH刷新整个arrays所需的延迟。 程序中arrays的大小是一个输入,我们将输入从1MB变为40MB,步长为2MB。 根据我们的理解,CLFLUSH应该刷新缓存中的内容。 所以我们期望看到整个arrays的刷新延迟首先在arrays大小方面线性增加,然后在arrays大小大于20MB(这是我们程序的LLC的大小)之后延迟应该停止增加。 然而,实验结果非常令人惊讶,如图所示。 数组大小超过20MB后,延迟不会停止增加。 我们想知道如果地址不在缓存中,CLFLUSH是否可能在CLFLUSH将地址刷出缓存之前引入地址? 我们还尝试在英特尔软件开发人员手册中进行搜索,但没有找到任何解释,如果地址不在缓存中,CLFLUSH会做什么。 以下是我们用于绘制图形的数据。 第一列是以KB为单位的数组大小,第二列是以秒为单位刷新整个数组的延迟。 任何建议/建议都不仅仅是值得赞赏的。 [改性] 以前的代码是不必要的。 尽管CLFLUSH具有相似的性能,但它可以更容易地在用户空间中完成。 所以我删除了凌乱的代码以避免混淆。 SCENARIO=Read Only 1024,.00158601000000000000 3072,.00299244000000000000 5120,.00464945000000000000 7168,.00630479000000000000 9216,.00796194000000000000 11264,.00961576000000000000 13312,.01126760000000000000 15360,.01300500000000000000 17408,.01480760000000000000 19456,.01696180000000000000 21504,.01968410000000000000 23552,.02300760000000000000 25600,.02634970000000000000 27648,.02990350000000000000 29696,.03403090000000000000 31744,.03749210000000000000 33792,.04092470000000000000 35840,.04438390000000000000 37888,.04780050000000000000 39936,.05163220000000000000 SCENARIO=Read and Write 1024,.00200558000000000000 3072,.00488687000000000000 5120,.00775943000000000000 7168,.01064760000000000000 9216,.01352920000000000000 11264,.01641430000000000000 13312,.01929260000000000000 15360,.02217750000000000000 17408,.02516330000000000000 19456,.02837180000000000000 21504,.03183180000000000000 23552,.03509240000000000000 […]

包容性还是排他性? 英特尔酷睿IvyBridge处理器中的L1,L2缓存

我使用的是Intel Core IvyBridge处理器,Intel(R)Core(TM)i7-3770 CPU @ 3.40GHz(L1-32KB,L2-256KB,L3-8MB)。 我知道L3是包容性的,并且在多个核心之间共享。 我想知道关于我的系统的以下内容 第1部分 : L1是包容性还是排他性? L2是包容性还是排他性? 第2部分 : 如果L1和L2都包含在内,那么为了找到L2的访问时间,我们首先声明一个大小超过L2缓存(256KB)的数组(1MB),然后开始访问整个数组以加载到L2缓存中。 之后,我们从开始索引到结束索引访问数组元素,步长为64B,因为缓存行大小为64B。 为了获得更准确的结果,我们重复这个过程(在索引,开始端访问数组元素)多次,比如100万次并取平均值。 我理解为什么这种方法给出了如下正确的结果 – 当我们访问大小超过L2高速缓存大小的数组时,整个数组从主存储器加载到L3,然后从L3加载到L2,然后L2加载到L1。 最近访问的是整个arrays的最后32KB在L1中。 由于包含属性和高速缓存一致性,整个arrays也存在于L2和L3高速缓存中。 现在,当我开始从启动索引再次访问数组时,该索引不在 L1缓存中,而是在L2缓存中,因此将存在缓存未命中,并且它将从L2缓存加载。 这样,整个arrays的所有元素都需要更长的访问时间,总的来说,我将获得整个arrays的总访问时间。 为了获得单一访问权限,我将取总访问量的平均值。 我的问题是 – 我是否正确? 提前致谢 。

为什么按位运算比旧微处理器上的加/减操作稍快?

我今天看到了这段摘录: 在大多数较旧的微处理器上,按位运算比加法和减法运算稍快,并且通常比乘法和除法运算快得多。 在现代体系结构中,情况并非如此:按位运算通常与添加速度相同(尽管仍然比乘法更快)。 我很好奇为什么按位操作比旧微处理器上的加/减操作稍快一些。 我能想到的只会导致延迟的是,实现加/减的电路取决于几级逻辑门(并行加法器和诸如此类),而按位运算则具有更简单的电路实现。 这是什么原因? 我知道算术和按位运算都在现代处理器的一个时钟内执行,但纯粹谈到电路的传播时间,理论上现在处理器中的延迟是不是仍然存在? 最后,我有一个关于按位移位操作执行的概念C问题: unsigned x = 1; x <<= 5; unsigned y = 0; y += 32; x和y都应该保持值32 ,但是它需要5个单独的左移来获得x到该值(如通过管道实现的按位移位)? 为了澄清,我纯粹是在询问电路行为而不是时钟周期数。

CPU和数据对齐

请原谅我,如果你觉得这已被无数次回答,但我需要回答以下问题! 为什么数据必须对齐(在4字节/ 8字节/ 2字节边界上)? 这里我怀疑的是,当CPU具有地址线Ax Ax-1 Ax-2 … A2 A1 A0时,可以顺序寻址存储器位置。 那么为什么需要在特定边界对齐数据呢? 在编译代码和生成可执行代码时如何找到对齐要求? 如果例如数据对齐是4字节边界,那是否意味着每个连续字节位于模4偏移处? 我怀疑的是,如果数据是4字节对齐,那意味着如果一个字节是1004那么下一个字节是1008(或1005)?