我看到一个简单的存储循环出乎意料地表现不佳,这个存储循环有两个存储:一个具有16字节的正向步长,另一个总是位于同一位置1,如下所示:
volatile uint32_t value;
void weirdo_cpp(size_t iters, uint32_t* output) {
uint32_t x = value;
uint32_t *rdx = output;
volatile uint32_t *rsi = output;
do {
*rdx = x;
*rsi = x;
rdx += 4; // 16 byte stride
} while (--iters > 0);
}
Run Code Online (Sandbox Code Playgroud)
在汇编这个循环可能3看起来像:
weirdo_cpp:
...
align 16
.top:
mov [rdx], eax ; stride 16
mov [rsi], eax ; never changes
add rdx, 16
dec rdi
jne .top
ret
Run Code Online (Sandbox Code Playgroud)
当访问的存储区域在L2中时,我希望每次迭代运行少于3个周期.第二个商店只是一直在同一个位置,应该添加一个周期.第一个商店意味着从L2引入一条线,因此每4次迭代也会驱逐一条线.我不确定你如何评估L2成本,但即使你保守估计L1只能在每个周期中执行以下操作之一:(a)提交商店或(b)从L2接收一行或(c)将一条线驱逐到L2,对于stride-16商店流,你会得到1 + 0.25 + …
我正在尝试使用优化一些C++(RK4)
__builtin_prefetch
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何预取整个结构.
我不明白const void *addr
读了多少.我想要下载from
和to
加载的值.
for (int i = from; i < to; i++)
{
double kv = myLinks[i].kv;
particle* from = con[i].Pfrom;
particle* to = con[i].Pto;
//Prefetch values at con[i++].Pfrom & con[i].Pto;
double pos = to->px- from->px;
double delta = from->r + to->r - pos;
double k1 = axcel(kv, delta, from->mass) * dt; //axcel is an inlined function
double k2 = axcel(kv, delta + 0.5 * k1, from->mass) * dt; …
Run Code Online (Sandbox Code Playgroud) 我正在编写一个程序来分析社交网络图.这意味着程序需要大量的随机内存访问.在我看来,预取应该有所帮助.这是从顶点的邻居读取值的一小段代码.
for (size_t i = 0; i < v.get_num_edges(); i++) {
unsigned int id = v.neighbors[i];
res += neigh_vals[id];
}
Run Code Online (Sandbox Code Playgroud)
我将上面的代码转换为下面的代码,并预取顶点的邻居值.
int *neigh_vals = new int[num_vertices];
for (size_t i = 0; i < v.get_num_edges(); i += 128) {
size_t this_end = std::min(v.get_num_edges(), i + 128);
for (size_t j = i; j < this_end; j++) {
unsigned int id = v.neighbors[j];
__builtin_prefetch(&neigh_vals[id], 0, 2);
}
for (size_t j = i; j < this_end; j++) {
unsigned int id = v.neighbors[j];
res …
Run Code Online (Sandbox Code Playgroud) 考虑以下汇编代码循环:
#include <iostream>
#define ADD_LOOP(i, n, v) \
asm volatile ( \
"movw %1, %%cx ;" \
"movq %2, %%rax ;" \
"movq $0, %%rbx ;" \
"for: ;" \
"addq %%rax, %%rbx ;" \
"decw %%cx ;" \
"jnz for ;" \
"movq %%rbx, %0 ;" \
: "=x"(v) \
: "n"(i), "x"(n) \
: "%cx", "%rax", "%rbx" \
);
int main() {
uint16_t iter(10000);
uint64_t num(5);
uint64_t val;
ADD_LOOP(iter, num, val)
std::cout << val << std::endl;
return 0; …
Run Code Online (Sandbox Code Playgroud) gcc ×3
assembly ×2
c++ ×2
optimization ×2
performance ×2
x86-64 ×2
built-in ×1
c ×1
prefetch ×1
x86 ×1