1 cache 性能及影響因素
1.1 內存訪問和性能比較
有如下測試代碼:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
long length = 64 * 1024 * 1024;
int *arr = malloc(64 * 1024 * 1024 * sizeof(int));
long i=0, j=0;
struct timeval tv1, tv2;
struct timezone tz;
unsigned long sec, usec;
for (i = 0; i < length; i++) arr[i] = i;
// 循環(huán)1
gettimeofday (&tv1, &tz);
for(j = 0; j < 10; j++) {
//每取一次arr[i], 通過 cache_line 順便把后面 15 個 arr[i] 都取過來了
for (i = 0; i < length; i++) arr[i] *= 3;
}
gettimeofday (&tv2, &tz);
if (tv2.tv_usec < tv1.tv_usec) {
usec = 1000000 + tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec - 1;
} else {
usec = tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec;
}
printf("time %ld.%06ld s\n", sec, usec);
// 循環(huán)2
gettimeofday (&tv1, &tz);
for(j = 0; j < 10; j++) {
for (i = 0; i < length; i += 16) arr[i] *= 3;
}
gettimeofday (&tv2, &tz);
if (tv2.tv_usec < tv1.tv_usec) {
usec = 1000000 + tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec - 1;
} else {
usec = tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec;
}
printf("time %ld.%06ld s\n", sec, usec);
return 0;
}
該測試代碼預先分配大量內存,并與一個數(shù)組指針管理,使其可以通過數(shù)組索引訪問該片申請內存,接著對該內存域進行預讀寫,使其在測試中不受 pagefault 影響測試結果。
該測試主要的測試點:
- 第一個循環(huán)按照字節(jié)順序讀寫相同固定數(shù)量的數(shù)據(jù)。
- 第二個循環(huán)跨 cacheline 讀取比第一次少 16 倍的數(shù)據(jù)量。
理論不考慮 cache 則讀寫時間應該是 第二次 * 16 = 第一次
,實際測試結果如下:
(1)HUAWEI Kunpeng 920
# ./a.out
time 2.522369 s
time 0.339671 s
# perf stat -- ./a.out
time 2.623479 s
time 0.307353 s
Performance counter stats for './a.out':
3,154.14 msec task-clock # 0.992 CPUs utilized
7 context-switches # 0.002 K/sec
1 cpu-migrations # 0.000 K/sec
6,024 page-faults # 0.002 M/sec
8,200,710,113 cycles # 2.600 GHz
15,203,228,361 instructions # 1.85 insn per cycle
<not supported> branches
76,472 branch-misses
3.180782182 seconds time elapsed
3.084959000 seconds user
0.069436000 seconds sys
(2)Phytium S2500(飛騰 S2500)
# ./a.out
time 5.085658 s
time 1.352258 s
# perf stat -- ./a.out
time 5.535788 s
time 0.826428 s
Performance counter stats for './a.out':
6,930.59 msec task-clock # 0.999 CPUs utilized
50 context-switches # 0.007 K/sec
25 cpu-migrations # 0.004 K/sec
14,731 page-faults # 0.002 M/sec
14,552,534,159 cycles # 2.100 GHz
15,281,585,654 instructions # 1.05 insn per cycle
<not supported> branches
254,832 branch-misses
6.934533427 seconds time elapsed
6.481427000 seconds user
0.450099000 seconds sys
可以看到兩臺機器第一次循環(huán)花費時間都遠小于第二次的 16 這個倍數(shù)。
原因是第一次循環(huán)讀寫會從內存按照 cacheline 大小加載連續(xù)內存到 cache 中,如果后續(xù)讀寫數(shù)據(jù)在 cache 中則可以高效讀寫數(shù)據(jù),而不會從內存中讀取。
而第二次循環(huán)跨 cacheline 讀寫數(shù)據(jù),每次均有可能從內存讀寫數(shù)據(jù)。
從上述測試中可以看到,cache 讀 cpu 讀寫性能影響非常大。并且從測試也可以看到鯤鵬機器的 cache 讀寫速率高于飛騰機器。
1.2 cache line 對性能的影響
從 1.1
中的測試能夠看到 cache 對性能的影響,而 cache 的 cacheline 的大小對性能提升也有著直接作用。
cache line 對 cache 性能影響尤為重要, 程序對 cacheline 的優(yōu)化會大幅提升運行性能, 這里對 1.1
中的例子進行測試, 將步長 16 從 1 依次成倍增長測試不同步長,測試相同次數(shù)獲取時延:
腳本如下:
# ./example2.sh
#set -x
work=./a.out
stride=1
for i in `seq 1 15`; do
perf stat -e cache-misses -e cache-references -e cpu-cycles -e instructions -e L1-dcache-load-misses -e L1-dcache-loads -e L1-dcache-store-misses -e L1-dcache-stores -- $work $stride
stride=$(($stride*2))
done
(1)HUAWEI Kunpeng 920
# ./example2.sh
stride = 1, time 2.817894 s
stride = 2, time 2.920336 s
stride = 4, time 3.495400 s
stride = 8, time 4.565321 s
stride = 16, time 6.297579 s
stride = 32, time 7.362044 s
stride = 64, time 7.982766 s
stride = 128, time 10.473204 s
stride = 256, time 9.676618 s
stride = 512, time 12.120638 s
stride = 1024, time 13.391726 s
stride = 2048, time 17.123795 s
stride = 4096, time 23.674495 s
stride = 8192, time 24.273880 s
stride = 16384, time 28.081542 s
可以看到讀寫時間隨讀寫的步進大小逐漸遞增至最后趨近平穩(wěn)。而在 16,1024 步進時有大幅變化。
上述現(xiàn)象說明 cacheline 大小對性能影響的變化。
當步進在 Dcache-L1 時,比如 64 字節(jié),此時在 Dcache-L1 中讀寫數(shù)據(jù)整體性能會非常好。
當步進從 L2 跨度到從 Dcache-L2 讀寫數(shù)據(jù)時,此時讀寫性能將會有一個明顯降低,同理 L3 時會繼續(xù)有個明顯變化幅度,直至最后趨于穩(wěn)定時,只能每次都從內存讀寫數(shù)據(jù)。
1.3 L1 和 L2 緩存大小
如 1.2
測試中,當在 cacheline 范圍內讀寫數(shù)據(jù)時性能最好,那么 cacheline 越大性能則會越好。
1.4 指令集并行性對 cache 性能的影響
有如下代碼:
int steps = 256 * 1024 * 1024;
int a[2];
// Loop 1
for (int i=0; i<steps; i++) { a[0]++; a[0]++; }
// Loop 2
for (int i=0; i<steps; i++) { a[0]++; a[1]++; }
循環(huán)上 loop2 比 loop1 更快兩個代碼有如下依賴:
- loop1 依賴關系
x = a[0] -> x++ -> a[0] = x -> y = a[0] -> y++ -> a[0] = y
- loop2 依賴關系
?x = a[0] -> x++ -> a[0] = x
y = a[1] -> y++ -> a[1] = y
即機器具有有并行性,它可以同時訪問 L1 中的兩個內存位置,loop1 中處理器無法利用這種指令級并行性,但是 loop2 可以,代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define barrier() __asm__ __volatile__("": : :"memory")
static long timediff(clock_t t1, clock_t t2)
{
long elapsed;
elapsed = ((double)t2 - t1) / CLOCKS_PER_SEC * 1000;
return elapsed;
}
int main(int argc, char *argv[])
{
long i=0, j=0;
clock_t start, end;
int a[2] = {0};
unsigned long steps = 2000 * 1024 * 1024;
// loop1
start=clock();
for (i = 0; i < steps; i++) {
a[0]++;
barrier();
a[0]++;
barrier();
}
end =clock();
printf("%lu\n", timediff(start,end));
// loop2
start=clock();
for (i = 0; i < steps; i++) {
a[0]++;
barrier();
a[1]++;
barrier();
}
end =clock();
printf("%lu\n", timediff(start,end));
return 0;
}
測試如下:
(1)HUAWEI Kunpeng 920
loop1 time 11.611784 s
loop2 time 6.526364 s
(2)Phytium S2500
loop1 time 15.546450 s
loop2 time 7.637472 s
(3)Intel? Xeon? Gold 5218
loop1 time 8.084105 s
loop2 time 6.649898 s
可以看到指令集并行性在能夠并行時性能都會有明顯提升,另外三臺機器中并行性最好的是華為鯤鵬,然而最好的并行性和因特爾 5218 持平,非并行性下 intel 具有最好的讀寫性能。
1.5 緩存關聯(lián)性對 cache 的影響
目前有三種映射緩存方式:
-
直接映射緩存
每個內存塊只能存儲在緩存中的一個特定插槽中。一種簡單的解決方案是將索引為 chunk_index 的塊映射到緩存槽 (chunk_index % cache_slots)。映射到同一插槽的兩個內存塊不能同時存儲在緩存中。
-
N路組相聯(lián)高速緩存
每個內存塊都可以存儲在緩存中 N 個特定插槽中的任何一個中。例如,在 16 路緩存中,每個內存塊可以存儲在 16 個不同的緩存槽中。通常,具有相同最低位的索引的塊將共享 16 個槽。
-
全關聯(lián)緩存
每個內存塊都可以存儲在緩存中的任何槽中。實際上,緩存的運行方式類似于哈希表。
直接映射緩存可能會發(fā)生沖突,當多個值競爭緩存中的同一個插槽時,它們會不斷相互驅逐,命中率直線下降。
全關聯(lián)高速緩存在硬件中實現(xiàn)起來既復雜又昂貴。
N 路組關聯(lián)高速緩存是處理器高速緩存的典型解決方案,因為它們在實現(xiàn)簡單性和良好的命中率之間取得了很好的平衡。
當前所有測試機器都是 N路組相聯(lián),需要計算每個 way,sets 使用 bit 再去推算每一組可能丟失命中的字節(jié)步長,這里沒有計算,略過。
1.6 錯誤的 cacheline 共享 (緩存一致性)
在多核機器上,緩存會遇到另一個問題,緩存一致性,也就是說多線程,多核之間并行對 cache 訪問一致性問題對性能同樣會造成嚴重影響。
在測試機器中,有 L1 L2 獨占的,也有超線程下共享 L1的。
這里有如下測試:
for ( int j = 0; j < 100000000; j++) {
s_counter[position] = s_counter[position] + 3;
}
使用四個不同的線程參數(shù) 0,1,2,3調用上述代碼和使用16,32,48,64調用上述代碼,16,32,48,64耗時比第一組小很多,這就是緩存一致性引起,代碼如下:
// example6.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
static int s_counter[1024] __attribute__ ((aligned (64)));
int aaa = 1;
static void update_counter(int posion)
{
for (int i = 0; i < 100000000; i++) {
s_counter[posion] = s_counter[posion] + 3;
}
}
static void *thread_func1(void *param)
{
if (aaa)
update_counter(0);
else
update_counter(16);
return NULL;
}
static void *thread_func2(void *param)
{
if (aaa)
update_counter(1);
else
update_counter(32);
return NULL;
}
static void *thread_func3(void *param)
{
if (aaa)
update_counter(2);
else
update_counter(48);
return NULL;
}
static void *thread_func4(void *param)
{
if (aaa)
update_counter(3);
else
update_counter(64);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t tid1, tid2, tid3, tid4;
if (argc != 1)
aaa = 0;
pthread_create(&tid1, NULL, thread_func1, NULL);
pthread_create(&tid2, NULL, thread_func2, NULL);
pthread_create(&tid3, NULL, thread_func3, NULL);
pthread_create(&tid4, NULL, thread_func4, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
pthread_join(tid4, NULL);
return 0;
}
測試如下:
(1)HUAWEI Kunpeng 920
# gcc -O0 -g example6.c -lpthread
[root@node-3 test_cache]# time ./a.out // 0,1,2,3
real 0m1.889s
user 0m6.994s
sys 0m0.000s
[root@node-3 test_cache]# time ./a.out 1 // 16,32,48,64
real 0m0.451s
user 0m1.439s
sys 0m0.000s
[root@node-3 test_cache]# time taskset -c 0 ./a.out
real 0m1.251s
user 0m1.240s
sys 0m0.000s
[root@node-3 test_cache]# time taskset -c 0 ./a.out 1
real 0m1.250s
user 0m1.239s
sys 0m0.000s
(1)Phytium S2500
# gcc -O0 -g example6.c -lpthread
[root@node-1 test_cache]# time ./a.out
real 0m0.467s
user 0m1.829s
sys 0m0.011s
[root@node-1 test_cache]# time ./a.out 1
real 0m0.432s
user 0m1.720s
sys 0m0.001s
[root@node-1 test_cache]# time taskset -c 0 ./a.out
real 0m1.724s
user 0m1.722s
sys 0m0.001s
[root@node-1 test_cache]# time taskset -c 0 ./a.out 1
real 0m1.727s
user 0m1.714s
sys 0m0.011s
1.7 硬件設計
在某些處理器上,如果 L1 緩存訪問來自不同 bank 的緩存行,則它們可以并行處理兩個訪問,如果它們屬于同一 bank,則可以串行處理,這是“硬件怪異”的一個奇怪例子:
static int A, B, C, D, E, F, G;
static void Weirdness()
{
for (int i = 0; i < 200000000; i++)
{
<something>
}
}
<something> Time
A++; B++; C++; D++; 719 ms
A++; C++; E++; G++; 448 ms
A++; C++; 518 ms
遞增字段 A、B、C、D 比遞增字段 A、C、E、G 花費的時間更長。
僅遞增 A 和 C 比遞增 A 和 C 以及 E 和 G花費的時間更長。
2 cpu cache benchmark 工具
2.1 使用 llcbench 工具對 cache 進行性能測試
LLCbench (底層表征基準測試 Low-Level Characterization Benchmarks) 是一個基準測試工具, 集成了 MPBench, CacheBench 和 BLASBench 測試方法。這里只使用其中的 CacheBench 測試緩存性能。(llcbench 工具目前可能需要一些科學上網(wǎng)才能獲?。?br> 測試步驟:
# tar -xvf llcbench-20170104.tar.gz
# cd llcbench;make;make linux-lam;make cache-bench;make cache-run
# make cache-scripts
# make cache-graph
測試大致原理: 對不同字節(jié)長度數(shù)組進行同樣步長的循環(huán)讀寫測試統(tǒng)計時間(同 1
中 1.1
測試類似,不過 llcbench 工具更加標準和準確),生成的測試數(shù)據(jù)如下:
(1)HUAWEI Kunpeng 920
- 全局測試
- numa 綁定最近節(jié)點:
numactl -C 24 -m 1 make cache-run
distances 10 - numa 綁定最遠節(jié)點:
numactl -C 24 -m 3 make cache-run
distances 24
通過跳變位置可以看到每個 cache 級別的大小,以及內存讀寫速率位置。同樣的 numa 對性能影響也是明顯的(體現(xiàn)在圖標最后一個坡段)。
2.2 使用 pts 工具對內存緩存帶寬進行測試
pts (phoronix-test-suite) 的 cachebench 測試底層同樣使用 llcbench 進行測試, 這里使用 pts 測試各平臺內存緩存帶寬。
測試步驟如下:
# ./install-sh # 安裝 pts
# phoronix-test-suite install pts/cachebench # 下載 cachebench 測試用例
# phoronix-test-suite run pts/cachebench # 運行 cachebench 測試
(1)HUAWEI Kunpeng 920
- 讀測試:
- 寫測試
- 讀-修改-寫測試:
- 測試報告: https://openbenchmarking.org/result/2302010-NE-KUNPENG3610
2.3 lmbench 對 L1, L2, L3 cache 時延及帶寬測試
lmbench 是一個微型評測工具, 它衡量兩個關鍵特征: 反應時間和帶寬。
使用工具集中的 stream 測試帶寬,對應的時延是在帶寬跑滿下的時延。
使用工具集中的 lat_mem_rd 測試時延,主要對應不同數(shù)據(jù)大小下的時延。
2.3.1 工具常規(guī)測試步驟
# 編譯問題
# make results LDFLAGS=-ltirpc
# yum -y install libtirpc libtirpc-devel
# cp /usr/include/tirpc/rpc/* /usr/include/rpc/ -rf
# ln -s /usr/include/tirpc/netconfig.h /usr/include
# 測試
# cd src
# make results
# make rerun; make rerun; make rerun; cd results; make LIST=<OS>; make ps;
一個示例對應結果如下:
Memory latencies in nanoseconds - smaller is better
(WARNING - may not be correct, check graphs)
------------------------------------------------------------------------------
Host OS Mhz L1 $ L2 $ Main mem Rand mem Guesses
--------- ------------- --- ---- ---- -------- -------- -------
easystack Linux 5.15.79 4083 1.2130 2.5860 8.6590 161.1
顯示結果分別為(單位納秒):
L1: L1 cache 時延
L2: L2 cache 時延
Main mem: 順序讀內存時延
Rand mem: 隨機訪問內存時延
Guesses: 當 L2 不存在時, 可能會打印 No L2 cache?
對應分布圖如下:
lmbench 常規(guī)測試可以很好反應各級別 cache 時延, 以及不同數(shù)據(jù)跨度下 cache 時延的變化, 不過 lmbench 測試對 arm64 平臺測試有問題, 且每次測試時間過長, 這里直接使用 stream 和 lat_mem_rd 進行測試。
2.3.2 stream 帶寬及時延測試
HUAWEI Kunpeng 920(同一個 numa 到不同 cpu 的時延及帶寬 (node -> cpux))
# for i in $(seq 0 24 95); do echo "cpu:$i -> node0"; numactl -C $i -m 0 ./stream -W 50 -N 50 -M 64M; done
cpu:0 -> node0
STREAM copy latency: 1.28 nanoseconds
STREAM copy bandwidth: 12546.05 MB/sec
STREAM scale latency: 1.31 nanoseconds
STREAM scale bandwidth: 12207.16 MB/sec
STREAM add latency: 1.94 nanoseconds
STREAM add bandwidth: 12381.71 MB/sec
STREAM triad latency: 2.18 nanoseconds
STREAM triad bandwidth: 11019.52 MB/sec
cpu:24 -> node0
STREAM copy latency: 1.47 nanoseconds
STREAM copy bandwidth: 10851.14 MB/sec
STREAM scale latency: 1.51 nanoseconds
STREAM scale bandwidth: 10610.51 MB/sec
STREAM add latency: 2.03 nanoseconds
STREAM add bandwidth: 11812.86 MB/sec
STREAM triad latency: 2.34 nanoseconds
STREAM triad bandwidth: 10247.19 MB/sec
cpu:48 -> node0
STREAM copy latency: 1.75 nanoseconds
STREAM copy bandwidth: 9152.87 MB/sec
STREAM scale latency: 2.54 nanoseconds
STREAM scale bandwidth: 6298.64 MB/sec
STREAM add latency: 2.35 nanoseconds
STREAM add bandwidth: 10191.17 MB/sec
STREAM triad latency: 3.81 nanoseconds
STREAM triad bandwidth: 6303.67 MB/sec
cpu:72 -> node0
STREAM copy latency: 1.84 nanoseconds
STREAM copy bandwidth: 8699.05 MB/sec
STREAM scale latency: 2.83 nanoseconds
STREAM scale bandwidth: 5661.04 MB/sec
STREAM add latency: 2.56 nanoseconds
STREAM add bandwidth: 9362.28 MB/sec
STREAM triad latency: 4.14 nanoseconds
STREAM triad bandwidth: 5792.24 MB/sec
2.3.2 lat_mem_rd 不同數(shù)據(jù)長度的時延測試
HUAWEI Kunpeng 920(同一個 numa 到不同 cpu 的時延 (node -> cpux))
# for i in $(seq 0 24 95); do echo "cpu:$i -> node0"; numactl -C $i -m 0 ./lat_mem_rd -W 10 -N 10 -t 64M; done
cpu:0 -> node0
"stride=64
0.00049 1.552
0.00098 1.552
0.00195 1.552
0.00293 1.552
...
0.10938 1.552
0.11719 1.552
0.12500 3.104
0.14062 3.104
0.15625 3.103
0.17188 3.104
...
0.46875 3.104
0.50000 3.106
0.56250 7.389
0.62500 9.385
0.68750 10.238
0.75000 11.680
0.81250 11.735
0.87500 13.077
2.3.2.1 lat_mem_rd 替代實驗
使用 memory_latency.c 對不同數(shù)據(jù)長度進行相同步長測試:
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
#define ONE p = (char **)*p;
#define FIVE ONE ONE ONE ONE ONE
#define TEN FIVE FIVE
#define FIFTY TEN TEN TEN TEN TEN
#define HUNDRED FIFTY FIFTY
static void usage()
{
printf("Usage: ./mem-lat -b xxx -n xxx -s xxx\n");
printf(" -b buffer size in KB\n");
printf(" -n number of read\n\n");
printf(" -s stride skipped before the next access\n\n");
printf("Please don't use non-decimal based number\n");
}
int main(int argc, char* argv[])
{
unsigned long i, j, size, tmp;
unsigned long memsize = 0x800000; /* 1/4 LLC size of skylake, 1/5 of broadwell */
unsigned long count = 1048576; /* memsize / 64 * 8 */
unsigned int stride = 64; /* skipped amount of memory before the next access */
unsigned long sec, usec;
struct timeval tv1, tv2;
struct timezone tz;
unsigned int *indices;
while (argc-- > 0) {
if ((*argv)[0] == '-') { /* look at first char of next */
switch ((*argv)[1]) { /* look at second */
case 'b':
argv++;
argc--;
memsize = atoi(*argv) * 1024;
break;
case 'n':
argv++;
argc--;
count = atoi(*argv);
break;
case 's':
argv++;
argc--;
stride = atoi(*argv);
break;
default:
usage();
exit(1);
break;
}
}
argv++;
}
char* mem = mmap(NULL, memsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
// trick3: init pointer chasing, per stride=8 byte
size = memsize / stride;
indices = malloc(size * sizeof(int));
for (i = 0; i < size; i++)
indices[i] = i;
// trick 2: fill mem with pointer references
for (i = 0; i < size - 1; i++)
*(char **)&mem[indices[i]*stride]= (char*)&mem[indices[i+1]*stride];
*(char **)&mem[indices[size-1]*stride]= (char*)&mem[indices[0]*stride];
register char **p = (char **) mem;
tmp = count / 100;
gettimeofday (&tv1, &tz);
for (i = 0; i < tmp; ++i) {
HUNDRED; //trick 1
}
gettimeofday (&tv2, &tz);
char **touch = p;
if (tv2.tv_usec < tv1.tv_usec) {
usec = 1000000 + tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec - 1;
} else {
usec = tv2.tv_usec - tv1.tv_usec;
sec = tv2.tv_sec - tv1.tv_sec;
}
printf("Buffer size: %ld KB, stride %d, time %ld.%06ld s, latency %.2f ns\n",
memsize/1024, stride, sec, usec, (sec * 1000000 + usec) * 1000.0 / (tmp *100));
munmap(mem, memsize);
free(indices);
}
mem-lat.sh文章來源:http://www.zghlxwxcb.cn/news/detail-622217.html
#set -x
work=./a.out
buffer_size=1
stride=64
for i in `seq 1 15`; do
taskset -ac 0 $work -b $buffer_size -s $stride
buffer_size=$(($buffer_size*2))
done
HUAWEI Kunpeng 920文章來源地址http://www.zghlxwxcb.cn/news/detail-622217.html
# ./mem-lat.sh
Buffer size: 1 KB, stride 64, time 0.001627 s, latency 1.55 ns
Buffer size: 2 KB, stride 64, time 0.001627 s, latency 1.55 ns
Buffer size: 4 KB, stride 64, time 0.001637 s, latency 1.56 ns
Buffer size: 8 KB, stride 64, time 0.001627 s, latency 1.55 ns
Buffer size: 16 KB, stride 64, time 0.001626 s, latency 1.55 ns
Buffer size: 32 KB, stride 64, time 0.001627 s, latency 1.55 ns
Buffer size: 64 KB, stride 64, time 0.001664 s, latency 1.59 ns
Buffer size: 128 KB, stride 64, time 0.003489 s, latency 3.33 ns
Buffer size: 256 KB, stride 64, time 0.003542 s, latency 3.38 ns
Buffer size: 512 KB, stride 64, time 0.003605 s, latency 3.44 ns
Buffer size: 1024 KB, stride 64, time 0.004646 s, latency 4.43 ns
Buffer size: 2048 KB, stride 64, time 0.004625 s, latency 4.41 ns
Buffer size: 4096 KB, stride 64, time 0.005523 s, latency 5.27 ns
Buffer size: 8192 KB, stride 64, time 0.006047 s, latency 5.77 ns
Buffer size: 16384 KB, stride 64, time 0.007000 s, latency 6.68 ns
到了這里,關于幾個影響 cpu cache 性能因素及 cache 測試工具介紹的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!