相关疑难解决方法(0)

PREFETCH和PREFETCHNTA指令之间的区别

PREFETCHNTA指令基本上用于通过预取器将数据从主存储器带到缓存,但是NT已知带有后缀的指令会跳过缓存并避免缓存污染。

那么PREFETCHNTA,与PREFETCH指令有何不同?

x86 assembly caching prefetch isa

6
推荐指数
1
解决办法
764
查看次数

在__uint128_t上最有效的popcount?

我需要以最有效(最快)的方式来弹出大小为128位的无符号变量。

  • 操作系统:Linux / Debian 9
  • 编译器:GCC 8
  • 处理器:Intel i7-5775C

尽管解决方案便携,甚至更好。

首先,GCC中有两种类型,分别是__uint128_tunsigned __int128。我猜他们最终还是一样,看不出有什么理由写丑陋的unsigned __int128东西,因此尽管它应该是新类型,但我更喜欢第一个,它与标准更加相似uint64_t。另外,英特尔拥有__uint128_t使用它的另一个原因(可移植性)。

我写了以下代码:

#include <nmmintrin.h>
#include <stdint.h>

static inline   uint_fast8_t    popcnt_u128 (__uint128_t n)
{
    const uint64_t      n_hi    = n >> 64;
    const uint64_t      n_lo    = n;
    const uint_fast8_t  cnt_hi  = _mm_popcnt_u64(n_hi);
    const uint_fast8_t  cnt_lo  = _mm_popcnt_u64(n_lo);
    const uint_fast8_t  cnt     = cnt_hi + cnt_lo;

    return  cnt;
}
Run Code Online (Sandbox Code Playgroud)

这是绝对最快的选择吗?

编辑:

我想到了另一个选择,它可能会(或不会)更快:

#include <nmmintrin.h>
#include <stdint.h>

union   Uint128 {
    __uint128_t …
Run Code Online (Sandbox Code Playgroud)

c gcc x86-64 intel micro-optimization

6
推荐指数
1
解决办法
319
查看次数

由于 Spectre Mitigation,Hardware Lock Elision 是否已经一去不复返了?

由于 Spectre 缓解,所有当前 CPU 都禁用了硬件锁定省略是否正确,并且任何尝试使用 HLE 内在函数/指令进行互斥都会导致通常的互斥?

这是否有可能在未来不会有类似 HLE 互斥体的东西来避免像 Spectre 这样的漏洞?

security x86 x86-64 speculative-execution intel-tsx

6
推荐指数
1
解决办法
398
查看次数

如何用c ++ 11 CAS实现ABA计数器?

我正在实现一个基于此算法的无锁队列,该算法使用计数器来解决ABA问题.但我不知道如何用c ++ 11 CAS实现这个计数器.例如,从算法:

E9:    if CAS(&tail.ptr->next, next, <node, next.count+1>)
Run Code Online (Sandbox Code Playgroud)

它是一个原子操作,意思是如果tail.ptr->next等于next,则tail.ptr->next指向node同时(原子地)产生next.count+1.但是,使用C++ 11 CAS,我只能实现:

std::atomic_compare_exchange_weak(&tail.ptr->next, next, node);
Run Code Online (Sandbox Code Playgroud)

这不可能next.count+1同时发生.

c++ multithreading lock-free lockless c++11

5
推荐指数
1
解决办法
1924
查看次数

关于“每个程序员应该了解的内存”中包含的有关缓存和预取的示例之一

乌尔里希·德雷珀(Ulrich Drepper)在他的出色著作中提出了一个测试基准,我无法完全确定。

他正在谈论缓存和预取。他首先展示了一个测试,其中他正在访问每个16字节的元素数组(一个指针和一个64位整数,每个元素都有一个指向下一个的指针,但实际上这并不重要),并且对于每个元素,他递增它的值加一。

然后,他继续显示另一个测试,其中他正在访问同一数组,但是这次他将每个元素的值与下一个元素的值之和存储。

然后比较了这两个测试的数据,他显示,工作集小于L2D $的总大小(但大于L1D $的总大小),第二个测试的性能要优于第一个测试,他的动机是从下一个元素读取的内容充当“强制预取”,从而提高了性能。

现在,我不明白的是,当我们不仅要预取该行,而且实际上是从该行读取并在之后立即使用该数据时,该读取如何充当预取?该读取停顿不应该像在第一次测试中访问新元素时发生的那样停顿吗?实际上,在我看来,我认为第二个示例与第一个示例非常相似,唯一的区别是我们存储在上一个元素中,而不是最近的一个元素中(并且我们将两个元素相加而不是递增) 。

为了更准确地参考实际文本,在第22页右第三段中讨论了所涉及的测试,其相对图形为下一页的图3.13。

最后,我将在此处报告相关图表,并进行裁剪。第一个测试对应于蓝色的“ Inc”行,第二个测试对应于绿色的“ Addnext0”行。作为参考,红色的“跟随”行不执行写操作,而仅执行顺序读操作。

在此处输入图片说明

optimization caching cpu-architecture prefetch micro-optimization

5
推荐指数
0
解决办法
164
查看次数

至强 CPU (E5-2603) 后向内存预取

在 Xeon CPU (E5-2603) 中,向后内存预取是否与前向内存预取一样快?

我想实现一个需要对数据进行前向循环和后向循环的算法。

由于每次迭代都需要上次迭代的结果,因此我无法颠倒循环的顺序。

谢谢你。

optimization performance x86 caching intel

5
推荐指数
1
解决办法
385
查看次数

为什么对于两个核心,同一核心(超线程)中的两个线程的L1写访问访问最差?

我已经制作了ac/c ++程序(printf和的混合std::)来了解不同的缓存性能.我想并行化一个计算大块内存的进程.我必须在相同的内存位置上进行多次计算,因此我会在结果上写入结果,覆盖源数据.当第一个微积分完成后,我再做一个以前的结果.

I've guessed if I have two threads, one making the first calculus, and the other the second, I would improve performance because each thread does half the work, thus making the process twice as fast. I've read how caches work, so I know if this isn't done well, it may be even worse, so I've write a small program to measure everything.

(See below for machine topology, CPU type and flags and source code.) …

c++ x86 multithreading

5
推荐指数
1
解决办法
191
查看次数

如果预取在加载之前没有完成,那么预取就没用了吗?

假设我们有这个伪代码,但它ptr不在任何 CPU 缓存中:

prefetch_to_L1 ptr
/* 20 cycles */
load ptr
Run Code Online (Sandbox Code Playgroud)

由于ptr在主存中,预取操作的延迟(从预取指令解码到ptr在L1高速缓存中可用)远大于20个周期。正在进行的预取是否会减少负载的延迟?或者预取除非在加载之前完成,否则就没用吗?

天真地(对内存系统如何工作没有太多了解)我可以看到它以两种方式工作:

  • 当 CPU 执行加载时,它会以某种方式识别出同一地址正在进行预取,并等待预取完成后再从 L1 加载。
  • CPU 发现该地址当前不在高速缓存中,并转到主内存,忽略并行执行的预取操作。

其中之一是正确的吗?还有我没有想到的第三种选择吗?我对 Skylake 特别感兴趣,但也只是想建立一些一般的直觉。

optimization performance intel cpu-architecture micro-architecture

5
推荐指数
0
解决办法
75
查看次数

如何系统地使用软件预取?

阅读何时应该使用预取?中接受的答案后 以及预取示例中的示例,我在理解何时实际使用预取方面仍然存在很多问题。虽然这些答案提供了预取很有用的示例,但它们没有解释如何在实际程序中发现它。看起来像是随机猜测。

我特别对 intel x86 的 C 实现(prefetchnta、prefetcht2、prefetcht1、prefetcht0、prefetchw)感兴趣,这些实现可以通过 GCC 的__builtin_prefetch内在函数访问。我想知道:

  • 我如何才能看到软件预取对我的特定程序有帮助?我想我可以使用 Intel Vtune 或 Linux 实用程序收集 CPU 分析指标(例如缓存未命中次数)perf。在这种情况下,什么指标(或它们之间的关系)表明有机会通过软件预取来提高性能?
  • 如何找到缓存未命中最严重的负载?
  • 如何查看发生未命中的缓存级别来决定使用哪个预取(0,1,2)?
  • 假设我发现一个特定的负载在特定的缓存级别中遭受缺失,我应该在哪里放置预取?例如,假设下一个循环出现缓存未命中
for (int i = 0; i < n; i++) {
   // some code
   double x = a[i];
   // some code
}
Run Code Online (Sandbox Code Playgroud)

我应该在加载之前还是之后放置预取a[i]?它应该指向前方多远a[i+m]?我是否需要担心展开循环以确保我仅在缓存行边界上预取,或者它几乎是免费的,就像nop数据已经在缓存中一样?是否值得__builtin_prefetch连续使用多个调用来一次预取多个缓存行?

c performance x86 profiling prefetch

5
推荐指数
1
解决办法
1725
查看次数

有谁有_mm256_stream_load_si256(非临时加载绕过缓存)实际上提高性能的示例吗?

考虑对大量浮点数据(数百 GB)进行大规模 SIMD 矢量化循环,理论上,这些数据应该受益于非时间(“流”,即绕过缓存)加载/存储。

使用非临时存储 (_mm256_stream_ps) 实际上确实比普通存储 (_mm256_store_ps) 显着提高了约 25% 的吞吐量

但是,当使用 _mm256_stream_load 而不是 _mm256_load_ps 时,我无法测量到任何差异。

有谁有一个可以使用 _mm256_stream_load_si256 来实际提高性能的示例?

(指令集和硬件是 AMD Zen2 上的 AVX2,64 核)

for(size_t i=0; i < 1000000000/*larger than L3 cache-size*/; i+=8 )
{
  #ifdef USE_STREAM_LOAD
  __m256 a = _mm256_castsi256_ps (_mm256_stream_load_si256((__m256i *)source+i));
  #else
  __m256 a = _mm256_load_ps( source+i );
  #endif

   a *= a;

  #ifdef USE_STREAM_STORE
  _mm256_stream_ps (destination+i, a);
  #else
  _mm256_store_ps (destination+i, a);
  #endif
}
Run Code Online (Sandbox Code Playgroud)

performance x86 hpc cpu-architecture avx

5
推荐指数
1
解决办法
617
查看次数