我试图找到一种方法来打败H/W预取器来检测流模式并以随机顺序访问4KB数据,这样就不会被H/W预取器检测和预取.
最初我想以随机模式访问所有偶数索引数据,因为H/W预取器总是预取下一个缓存行(所以当我访问偶数索引时,下一个奇数索引数据已被预取).
我编写代码以随机模式访问所有偶数索引数据,但结果表明预取器检测到模式(不知道如何?没有固定步幅,都是随机步幅)
我正在调查原因 - 为什么会发生这种情况,然后我在英特尔发现了这篇文章; https://software.intel.com/en-us/forums/topic/473493
根据John D. McCalpin博士的说法,"带宽博士,
在"Intel 64和IA-32架构优化参考手册"(文档248966-028,2013年7月)的第2.2.5.4节中,它指出,
流式传输器预取器"[d]检测并维护多达32个数据访问流.对于每个4K字节页面,您可以维护一个前向流和一个后向流.
这意味着L2硬件预取器跟踪最近访问的16个4KiB页面,并记住这些页面的足够访问模式以跟踪一个前向流和一个后向流.因此,要通过"随机"提取来击败L2流式传输器预取器,只需确保在对先前引用的页面进行第二次引用之前访问超过15个其他4 KiB页面.因此,"随机"提取序列可以由超过16个4个KiB页码的随机排列组成,每个页面内具有随机偏移.(我的排列列表通常至少使用32页.)
所以这意味着在访问相同4KB页面的两个不同随机索引之间,我们需要访问至少16个4KB页面来击败H/W预取器.
我已经实现了John D. McCalpin建议的概念,但结果再次表明h/w预取器没有被击败.它能够检测一些模式和预取数据(参见示例输出).我有20-40个4KB页面的不同访问页数,但结果没有改进/变化.
这是我的代码:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#ifndef _POSIX_THREAD_PROCESS_SHARED
#error This system does not support process shared mutex
#endif
#define MAX_COUNT 3000
#define INDEX (40*1024) // size of DUMMY 40 4KB pages
inline void clflush(volatile void *p)
{
asm volatile ("clflush (%0)" :: "r"(p));
}
unsigned long probe(char *adrs) {
volatile unsigned long …
Run Code Online (Sandbox Code Playgroud) 我试图理解共享内存概念的基础.我试图创建一个具有一个函数和一个STATIC数组变量的共享库.我想通过该共享库的功能访问静态数组变量.
这是我的共享库
//foo.c
#include <stdio.h>
static int DATA[1024]={1 ,2 ,3 ,...., 1024};
inline void foo(void)
{
int j, k=0;
for(j=0;j<1024;j++)
{
k=DATA[j];
}
k+=0;
}
Run Code Online (Sandbox Code Playgroud)
我已按照共享库中的说明创建了共享库对象(libfoo.so)
现在我的问题是
1>如果我从两个不同的程序(program1和program2)访问foo(),那么program1和program2会有单独的foo()函数副本吗?
2> program1和program2 会有单独的静态DATA数组副本吗?
3>它们会加载到相同的物理内存位置吗?如果单独加载静态DATA数组,有没有办法强制/加载到相同的内存位置?
4>有没有办法找到为program1和program2存储静态DATA数组的位置?
我在linux下使用gcc.任何帮助将受到高度赞赏.谢谢.
我试图了解CPU如何在具有不同线程的不同进程之间分配.我有两个程序Program1和Program2.
Program1有5个线程,而Program2只有主线程.
情景-1:
terminal-1 : ./Program1
terminal-2 : ./Program2
Run Code Online (Sandbox Code Playgroud)
当我在一个终端中运行Program1而在另一个终端中运行Program2时,对于Program1,CPU分配为50%,对于Program2,CPU分配为50%.Program1的每个线程都获得10%(Program1累积50%)
这表明,无论进程具有什么线程,每个进程都将获得相同的CPU份额.这表明CPU分配是在进程级别完成的.
pstree显示
??bash???P1???5*[{P1}]
??bash???P2???{P2}
Run Code Online (Sandbox Code Playgroud)
情景-2:
terminal-1 : ./Program1 & ./Program2
Run Code Online (Sandbox Code Playgroud)
当我在SAME终端中运行Program1和Program2时,对于Program1和Program2的所有线程,CPU分配都是相同的.这意味着Program1的每个线程几乎达到17%(累计Program1达到83%),Program2也达到17%.这表明CPU分配是在线程级别完成的.
pstree显示
??bash???P1???5*[{P1}]
? ??P2
Run Code Online (Sandbox Code Playgroud)
我使用的是Ubuntu 12.04.4 LTS,kernel-config-3.11.0-15-generic.我也使用了Ubuntu 14.04.4,kernel-3.16.x并得到了类似的结果.
任何人都可以解释一下LINUX KERNEL的CPU调度程序如何区分SCENARIO-1和SCENARIO-2?
我认为CPU调度程序在分配CPU之前在某处区分SCENARIO.要了解CPU调度程序如何区分SCENARIO-1和SCENARIO-2,我已经下载了Linux内核源代码.
但是,我没有在源代码中找到区分SCENARIO-1和SCENARIO-2的地方.
如果有人向我指出CPU调度程序区分SCENARIO-1和SCENARIO-2的源代码或函数,那将会很棒.
提前致谢.
注意:虽然Ubuntu基于Debian,但令人惊讶的是,在Debian 8(kernel-3.16.0-4-686-pae)中,两个SCENARIO的CPU分配都是在Thread级别完成的,这意味着Program1的每个线程都接近17%(累计为Program1)获得83%),而Program2也获得17%.
这是代码:Program1(有5个线程)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// Let us create a global variable to change it in threads
int g = 0;
// The function to be executed by all threads
void *myThreadFun(void *vargp)
{
// Store the value …
Run Code Online (Sandbox Code Playgroud) 尝试在我的Core i7系统中禁用硬件预取程序时,我收到错误.我按照链接按照方法如何以编程方式禁用硬件预取?
在我的系统中
grep -i msr/boot/config - $(uname -r)
CONFIG_X86_DEBUGCTLMSR = Y
CONFIG_X86_MSR = Y
CONFIG_SCSI_ARCMSR =米
这是我的错误消息
root @ ./rdmsr 0x1a0
850089
[root @ ./wrmsr -p 0 0x1a0 0x850289(禁用Core i7中的硬件预取器)
wrmsr:pwrite:输入/输出错误
我在禁用Adjacent cache line prefetcher时收到同样的错误
知道如何解决这个问题吗?提前致谢 .
我有Intel Core IvyBridge处理器,Intel®Core™i7-3770 CPU @ 3.40GHz(L1-32KB,L2-256KB,L3-8MB)。我知道L3具有包容性,并且在多个内核之间共享。我想了解有关我的系统的以下内容
第1部分 :
第2部分 :
如果L1和L2都包括在内,则为了找到L2的访问时间,我们首先声明一个大小大于L2高速缓存(256KB)的数组(1MB),然后开始访问整个数组以加载到L2高速缓存中。之后,由于缓存行大小为64B,所以我们以64B的步长从开始索引到结束索引访问数组元素。为了获得更好的准确结果,我们重复此过程(访问索引处index,开始到末尾的数组元素)多次,比如说进行一百万次并取平均值。
我的理解为什么这种方法会给出正确的结果,如下所示:当我们访问大小大于L2缓存大小的数组时,整个数组将从主内存加载到L3,然后从L3加载到L2,再从L2加载到L1。整个数组的最后32KB位于L1中,因为最近已对其进行了访问。由于具有包容性和高速缓存一致性,整个阵列也存在于L2和L3高速缓存中。现在,当我从起始索引再次开始访问数组时,起始索引不在 L1高速缓存中,而是在L2高速缓存中,因此将出现高速缓存未命中,并且将从L2高速缓存中加载它。这样,整个数组的所有元素将需要更长的访问时间,总的来说,我将获得整个数组的总访问时间。要获得单次访问权限,我将获得总访问次数的平均值。
我的问题是- 我正确吗?
提前致谢 。
我正在阅读有关Intel Core i7系统中可用的不同预取器的信息。我进行了实验,以了解何时调用这些预取器。
这些是我的发现
L1 IP预取器在3次高速缓存未命中后开始预取。它仅在缓存命中时预取。
L2相邻行预取器在第一个高速缓存未命中后开始预取,并在高速缓存未命中时预取。
L1 H / W(跨步)预取器在第一次高速缓存未命中后开始预取,并在高速缓存命中时进行预取。
我无法了解DCU预取器的行为。它何时开始预取或调用?它是否在缓存命中或未命中时预取下一个缓存行?
我在其中提到的英特尔文档披露-hw-prefetcher中进行了探索-DCU预取器将下一个缓存行提取到L1-D缓存中,但是在开始预取时没有明确的信息。
谁能解释DCU预取器何时开始预取?
我从program1访问共享库(共享数组数据结构),并找到读取该数组的所有元素的访问时间.我得到大约17000个滴答,而只有Program1单独执行.
现在,当我首先在另一个选项卡中执行program2(具有空的while循环以保持终止)时,然后运行program1并测量访问时间以读取该数组的所有元素.令我惊讶的是,与之前只有Program1执行的场景相比,我获得了8000ticks.
看起来只有program1执行时才需要花费更多时间来读取数组,而有2个程序时,program1正在执行与之前相同的任务,而program2通过while循环使CPU保持忙碌状态.预计存在program1的访问时间会更长,而实际结果则相反.
为什么会这样?
这是共享库
#include <stdio.h>
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;
}
Run Code Online (Sandbox Code Playgroud)
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();
printf("Time5=%llu\n",end-start);
sleep(2);
start=timer();
foo();
end=timer();
printf("after sleep(2)\n");
printf("Time6=%llu\n",end-start);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
程序2
int main(void)
{
while(1)
{}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
CASE1(仅运行Program1)
产量
Time1=17918
Time2=17672
Time3=17816
after sleep(1) …
Run Code Online (Sandbox Code Playgroud) 是否有任何仍然相关的CPU(Intel/AMD/Atom)不支持SSSE3指令?
没有SSSE3的最新CPU是什么?
L1/L2缓存包含在Intel和L1/L2缓存中是8路相关性,意味着在一组中存在8条不同的缓存线.缓存行作为一个整体操作,意味着如果我想从缓存行中删除几个字节,整个缓存行将被删除,而不是我想要删除的那些字节.我对吗 ?
现在,我的问题是,无论是通过某个其他进程还是使用clflush(手动逐出缓存行/块),从缓存中删除/逐出集合的缓存行,系统是否会将该缓存行的驱逐数据存储在某处(在任何缓冲区,寄存器等),以便下次它可以从该位置加载数据以减少延迟,与从主存储器或更高级别的缓存加载数据相比,或者 它 总是使缓存中的数据无效并且下次加载下一个更高级别的数据.
任何建议或文章的任何链接将受到高度赞赏.提前致谢.
architecture operating-system processor cpu-architecture computer-architecture
我已经安装了最新版本的OpenSSL.我只是尝试编译并运行OpenSSL_aes程序.
在使用gcc -Wall openssl_aes.c -lcrypto进行编译时出现以下错误.我尽力解决了这个问题,但无法解决这个编译错误.
openssl_aes.c: In function ‘aes_encrypt’:
openssl_aes.c:51:22: error: ‘AES_BLOCK_SIZE’ undeclared (first use in this function)
int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
^
openssl_aes.c:51:22: note: each undeclared identifier is reported only once for each function it appears in
openssl_aes.c: In function ‘aes_decrypt’:
openssl_aes.c:75:45: error: ‘AES_BLOCK_SIZE’ undeclared (first use in this function)
unsigned char *plaintext = malloc(p_len + AES_BLOCK_SIZE);
^
Run Code Online (Sandbox Code Playgroud)
编辑:
当我#include<openssl/aes.h>
按照@ martin 添加时,编译问题就解决了.
现在,gcc -Wall openssl_aes.c -lcrypto已成功编译.
但是,当我尝试运行程序(运行我使用 - ./a.out)时,我得到了以下错误 分段错误(核心转储) …
我在装配中经历了这个链接延迟,以增加装配延迟.我想通过添加不同的延迟值来执行一些实验.
生成延迟的有用代码
; start delay
mov bp, 43690
mov si, 43690
delay2:
dec bp
nop
jnz delay2
dec si
cmp si,0
jnz delay2
; end delay
Run Code Online (Sandbox Code Playgroud)
我从代码中理解的是,延迟与执行nop指令所花费的时间成比例(43690x43690).所以在不同系统和不同版本的操作系统中,延迟会有所不同.我对吗?
任何人都可以向我解释如何计算nsec的延迟量,下面的汇编代码正在生成,以便我可以结束我在实验设置中添加的延迟的实验?
这是我用来生成延迟而不理解使用43690值的逻辑的代码(我在原始源代码中只对一个循环使用了一个循环).为了产生不同的延迟(不知道它的值),我只改变了数字43690到403690或其他值.
32位操作系统中的代码
movl $43690, %esi ; ---> if I vary this 4003690 then delay value ??
.delay2:
dec %esi
nop
jnz .delay2
Run Code Online (Sandbox Code Playgroud)
这个汇编代码会产生多少延迟?
如果我想在microsec中生成100nsec或1000nsec或任何其他延迟,那么我需要在寄存器中加载什么初始值?
我使用的是ubuntu 16.04(32位和64位),Intel(R)Core(TM)i5-7200U CPU @ 2.50GHz和Core-i3 CPU 3470 @ 3.20GHz处理器.
先感谢您.
我正在尝试使用 cpu 频率缩放来设置 cpu 频率。在我的系统中,只支持 powersave 、 performance frequency-scaling-governor 。在其他文档中解释过,默认情况下,intel_pstate 是启用的,它只支持 powersave ,performance frequency-scaling-governor,解决方案是禁用 intel_pstate。所以我尝试禁用如下
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="intel_pstate=disable"
sudo update-grub
Run Code Online (Sandbox Code Playgroud)
重新启动时,启用 intel_pstate。
所以,我再次对 grub 进行了以下更改
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="intel_pstate=disable acpi=force"
sudo update-grub
Run Code Online (Sandbox Code Playgroud)
重新启动时,它仍然显示 intel_pstate 已启用。
当我执行以下命令时,
$ cpupower -c all frequency-info
analyzing CPU 7:
driver: intel_pstate
CPUs which run at the same hardware frequency: 7
CPUs which need to have their frequency coordinated by software: 7
maximum transition latency: Cannot determine or is not supported.
hardware limits: 1.60 GHz …
Run Code Online (Sandbox Code Playgroud) linux ×7
c ×6
intel ×3
processor ×3
x86 ×3
assembly ×2
cpu-cache ×2
linux-kernel ×2
performance ×2
prefetch ×2
architecture ×1
cpu ×1
delay ×1
gcc ×1
msr ×1
openssl ×1
optimization ×1
simd ×1