- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Whiskey Lake i7-8565U
我正在尝试学习如何手动编写基准测试(不使用任何基准测试框架),该示例以内存复制例程为例,其中常规写入和非临时写入WB内存,并希望进行某种形式的回顾。
宣言:
void *avx_memcpy_forward_llss(void *restrict, const void *restrict, size_t);
void *avx_nt_memcpy_forward_llss(void *restrict, const void *restrict, size_t);
avx_memcpy_forward_llss:
shr rdx, 0x3
xor rcx, rcx
avx_memcpy_forward_loop_llss:
vmovdqa ymm0, [rsi + 8*rcx]
vmovdqa ymm1, [rsi + 8*rcx + 0x20]
vmovdqa [rdi + rcx*8], ymm0
vmovdqa [rdi + rcx*8 + 0x20], ymm1
add rcx, 0x08
cmp rdx, rcx
ja avx_memcpy_forward_loop_llss
ret
avx_nt_memcpy_forward_llss:
shr rdx, 0x3
xor rcx, rcx
avx_nt_memcpy_forward_loop_llss:
vmovdqa ymm0, [rsi + 8*rcx]
vmovdqa ymm1, [rsi + 8*rcx + 0x20]
vmovntdq [rdi + rcx*8], ymm0
vmovntdq [rdi + rcx*8 + 0x20], ymm1
add rcx, 0x08
cmp rdx, rcx
ja avx_nt_memcpy_forward_loop_llss
ret
#include <stdio.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <immintrin.h>
#include <x86intrin.h>
#include "memcopy.h"
#define BUF_SIZE 128 * 1024 * 1024
_Alignas(64) char src[BUF_SIZE];
_Alignas(64) char dest[BUF_SIZE];
static inline void warmup(unsigned wa_iterations, void *(*copy_fn)(void *, const void *, size_t));
static inline void cache_flush(char *buf, size_t size);
static inline void generate_data(char *buf, size_t size);
uint64_t run_benchmark(unsigned wa_iteration, void *(*copy_fn)(void *, const void *, size_t)){
generate_data(src, sizeof src);
warmup(4, copy_fn);
cache_flush(src, sizeof src);
cache_flush(dest, sizeof dest);
__asm__ __volatile__("mov $0, %%rax\n cpuid":::"rax", "rbx", "rcx", "rdx", "memory");
uint64_t cycles_start = __rdpmc((1 << 30) + 1);
copy_fn(dest, src, sizeof src);
__asm__ __volatile__("lfence" ::: "memory");
uint64_t cycles_end = __rdpmc((1 << 30) + 1);
return cycles_end - cycles_start;
}
int main(void){
uint64_t single_shot_result = run_benchmark(1024, avx_memcpy_forward_llss);
printf("Core clock cycles = %" PRIu64 "\n", single_shot_result);
}
static inline void warmup(unsigned wa_iterations, void *(*copy_fn)(void *, const void *, size_t)){
while(wa_iterations --> 0){
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
copy_fn(dest, src, sizeof src);
}
}
static inline void generate_data(char *buf, size_t sz){
int fd = open("/dev/urandom", O_RDONLY);
read(fd, buf, sz);
}
static inline void cache_flush(char *buf, size_t sz){
for(size_t i = 0; i < sz; i+=_SC_LEVEL1_DCACHE_LINESIZE){
_mm_clflush(buf + i);
}
}
avx_memcpy_forward_llss
中位数:44479368个核心周期
real 0m0,217s
user 0m0,093s
sys 0m0,124s
avx_nt_memcpy_forward_llss
中位数:24053086核心周期
real 0m0,184s
user 0m0,056s
sys 0m0,128s
taskset -c 1 ./bin
运行基准测试时得到的结果
cpuid
,以便开始使用干净的CPU资源进行测量,以避免由于先前的飞行指令而导致停顿。我添加了内存碎片作为编译屏障,并添加了
lfence
以避免
rdpmc
被执行。
最佳答案
基准测试应尽可能以尽可能多的“健全性检查”的方式报告结果。在这种情况下,启用这种检查的几种方法包括:
对于涉及主内存带宽的测试,结果应以可直接与系统已知DRAM峰值带宽进行比较的单位表示。对于Core i7-8565U的典型配置,这是2个通道* 8字节/传输* 24亿个传输/秒= 38.4 GB / s(另请参阅下文第(6)项。)
对于涉及在存储器层次结构中任何地方进行数据传输的测试,结果应包括对“内存占用空间”大小(访问的不同缓存行地址的数量乘以缓存行大小)的清晰描述,以及重复的次数。转移。您的代码在这里很容易阅读,并且大小对于主内存测试是完全合理的。
对于任何定时测试,都应包括绝对时间,以便与合理的定时开销进行比较。仅使用CORE_CYCLES_UNHALTED计数器将无法直接计算经过的时间(尽管测试时间足够长,因此计时开销可以忽略不计)。
其他重要的“最佳实践”原则:
任何使用RDPMC指令的测试都必须绑定到单个逻辑处理器。结果的显示方式应向读者确认已采用这种绑定。在Linux中强制执行此类绑定的常见方法包括使用“任务集”或“ numactl --physcpubind = [n]”命令,或包括使用单个允许的逻辑处理器对“ sched_setaffinity()”进行内联调用,或设置环境变量这会导致运行时库(例如OpenMP)将线程绑定到单个逻辑处理器。
使用硬件性能计数器时,需要格外小心,以确保计数器的所有配置数据均可用并正确描述。上面的代码使用RDPMC读取IA32_PERF_FIXED_CTR1,其事件名称为CPU_CLK_UNHALTED。事件名称的修饰符取决于IA32_FIXED_CTR_CTRL(MSR 0x38d)位7:4的编程。没有从所有可能的控制位到事件名称修饰符的映射的通用方法,因此最好提供IA32_FIXED_CTR_CTRL的完整内容以及结果。
CPU_CLK_UNHALTED性能计数器事件是用于对处理器行为直接随处理器核心频率扩展的部分进行基准测试的正确方法,例如指令执行和仅涉及L1和L2高速缓存的数据传输。内存带宽涉及处理器的某些部分,这些部分的性能不会直接随处理器频率而扩展。特别是,在不强制执行固定频率操作的情况下使用CPU_CLK_UNHALTED使得无法计算经过时间(上述(1)和(3)要求)。在您的情况下,RDTSP比RDPMC更容易-RDTSC不需要将进程绑定到单个逻辑处理器,它不受其他配置MSR的影响,并且可以直接计算经过的时间(以秒为单位)。
进阶:对于涉及存储器层次结构中数据传输的测试,控制缓存内容和缓存内容的状态(干净或脏)并提供对“ before”和“ after”状态的明确描述很有帮助。结果。给定数组的大小,您的代码应使用源数组和目标数组的部分组成部分完全填充高速缓存的所有级别,然后刷新所有这些地址,从而使(几乎)完全无效的高速缓存层次结构(干净)条目。
高级:将CPUID用作序列化指令几乎对基准测试毫无用处。尽管可以保证排序,但执行时间也很长-Agner Fog的“指令表”以100-250个周期报告它(大概取决于输入参数)。 (更新:短时间间隔内的测量总是非常棘手。CPUID指令执行时间长且可变,并且不清楚微编码实现对处理器内部状态的影响。在某些情况下可能会有所帮助,但不应将其视为基准测试中自动包含的内容。对于长时间间隔的测量,可以忽略跨测量边界的乱序处理,因此不需要CPUID。)
高级:仅当您以非常精细的粒度(少于几百个周期)进行测量时,才可以在基准测试中使用LFENCE。 http://sites.utexas.edu/jdm4372/2018/07/23/comments-on-timing-short-code-sections-on-intel-processors/上有关此主题的更多说明
如果我假设您的处理器在测试过程中以4.6 GHz的最大Turbo频率运行,则报告的周期数分别对应于9.67毫秒和5.23毫秒。将其插入“健全性检查”显示:
假设第一种情况执行一次读取,一次分配和一次回写(每个128MiB),则相应的DRAM流量为27.8GB / s + 13.9 GB / s = 41.6 GB / s ==峰值的108%。
假设第二种情况执行一个读取和一个流存储(每个128MiB),则相应的DRAM流量为25.7 GB / s + 25.7 GB / s = 51.3 GB / s =峰值的134%。
这些“健全性检查”的失败告诉我们,该频率不可能高达4.6 GHz(并且可能不高于3.0 GHz),但大多数情况只是表明需要明确地测量经过的时间...。
您在优化手册中对流存储效率低下的报价仅适用于无法合并为完整缓存行传输的情况。您的代码将遵循“最佳实践”建议存储到输出缓存行的每个元素(写入同一行的所有存储指令都将连续执行,并且每个循环仅生成一个存储流)。不可能完全阻止硬件破坏流媒体商店,但是在您的情况下,它应该非常少见-可能只有百万分之一。检测部分流存储是一个非常高级的主题,要求在“非核心”中使用文档记录不佳的性能计数器,和/或通过查找升高的DRAM CAS计数(可能是由于其他原因)间接检测部分流存储。有关流媒体商店的更多说明,请参见http://sites.utexas.edu/jdm4372/2018/01/01/notes-on-non-temporal-aka-streaming-stores/
关于c - 一次性对内存副本进行基准测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60191343/
我正在阅读一些基准测试技巧,并在此站点上发现了一条提示“重新启动 MySQL 服务器以消除任何不需要的缓存因素”:http://blog.monitor.us/2012/09/the-gold-sta
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我在linux上测量cpu时间和排序算法的时间。我使用getrusage来测量cpu时间,并使用clock_gettime CLOCK_MONOTONIC来获取墙时间。尽管我注意到cpu时间大于墙上时
我可以阅读很多关于 OpenCL 的文章,它似乎是最有前途的(唯一的?)多架构库。 OpenCL应该是第一个并行架构编程标准,它最终会被大部分程序员采用。这很好,但是从 native 编程库迁移到 O
我想在不使用外部依赖项的情况下对一些 Lua 进行基准测试。我目前正在使用 os.clock: local function dummy() end local start = os.clock()
我对此很好奇。 我想检查哪个函数更快,所以我编写了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
有没有办法在项目的开发阶段对 SQL 查询进行基准测试? 有问题的表中只有几个示例行,但我想在行数达到数千、数百万、数十亿、数万亿、数亿等等之前对一些查询进行基准测试 用数千行样本数据填充表格是唯一的
我正在尝试测量使用 rdtsc 执行函数“check()”所需的时间,如下所示: a = rdtsc(); check(pw); b = rdtsc(); return (b-a); 但是,我收到的时
我想在我的 Hadoop 集群上执行基准测试和性能测试。我知道 hadoop-mapreduce*test*.jar 和 hadoop-mapreduce-examples*.jar 有很多用于基准测
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
这个现在非常常见的算法问题是在白板考试期间由监考人员提出的。我的工作是观察、倾听和客观判断给出的答案,但我无法控制这个问题,也无法与回答者互动。 给了五分钟的时间分析问题,考生可以写项目符号,伪代码(
我把代码从 http://www.bonto.ch/blog/2011/12/08/json-libraries-for-ios-comparison-updated/并在我的本地机器上进行了测试。
我正在尝试使用 MySQL 基准测试来测试一些查询。但是,我遇到了一个错误。 SELECT benchmark (10000, (select title from user)); 作为返回,我得到了
我很好奇这个。 我想检查哪个函数更快,所以我创建了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我经常想比较同一函数的多个实现的运行时性能。对于个人输入,标准是一个很好的工具。 但是有什么简单的方法可以在不同的输入大小上绘制代码的性能,例如看算法复杂度? 理想情况下,我向库传递一个类型为 Ben
我有一系列旨在完成相同功能的功能。相同的输入产生相同的输出,但是执行这些输出所需的时间因功能而异。我想确定哪个是“最快”的,我想对自己的测量结果具有“统计学意义”有一定的信心。 细读Wikipedia
我想编写一个加载基准测试,它以编译时已知的步幅跨过给定的内存区域,并在该区域的末尾(2 的幂)使用尽可能少的非加载指令进行包装有可能。 例如,给定步长 4099,rdi 中的迭代计数以及 rsi 中指
我有多个组件与 RabbitMQ 相连。有些是生产者和消费者。我需要对我的系统进行基准测试/负载测试。我需要确保消费者每秒可以处理 N 条消息。我在互联网上做了一些搜索,但还没有真正找到任何东西。有没
是否有任何基准或研究来比较这两个 IDE --稳定性-- 开发人员生产力 - 特征 - 表现-- 等等 最佳答案 我是 Eclipse 用户(不是自愿的)。不确定稳定性,但性能方面 NetBeans
我是一名优秀的程序员,十分优秀!