标签: loop-unrolling

为什么 Hotspot JIT 不为长计数器执行循环展开?

我刚刚阅读了 Java Magazine 文章Loop Unrolling。作者在那里演示了for带有int计数器的简单循环是通过循环展开优化编译的:

private long intStride1()
{
    long sum = 0;
    for (int i = 0; i < MAX; i += 1)
    {
        sum += data[i];
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

但是,他们随后通过将计数器类型切换为 来显示一切都发生了变化long

private long longStride1()
{
    long sum = 0;
    for (long l = 0; l < MAX; l++)
    {
        sum += data[(int) l];
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

这会通过以下方式更改输出程序集:

  1. 介绍安全点
  2. 不执行展开

这会显着降低吞吐量性能。

为什么 64 位 HotSpot VM 不为long计数器执行循环展开?为什么第二种情况需要安全点,而第一种情况不需要?

java jit jvm-hotspot compiler-optimization loop-unrolling

7
推荐指数
1
解决办法
101
查看次数

使用C++中的模板展开循环,并进行部分特化

我正在尝试使用模板在C++中展开循环,如下所示.

#include <iostream>

template< class T, T i >
struct printDown {
    static void run(void) {
        std::cout << i << "\n";
        printDown< T, i - 1 >::run();
    }
};

template< class T >
struct printDown< T, 0 > {
    static void run(void) {
        std::cout << 0 << "\n";
    }
};

int main(void) {
    printDown< int, 10 >::run();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在Cygwin中编译w/g ++ 3.4.4时,我收到以下错误.

tmp.cpp:12:错误:类型T' of template argument0'取决于模板参数

我究竟做错了什么?我是否需要以某种方式注释0来说它是T型?

提前致谢.

c++ templates partial-specialization specialization loop-unrolling

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

在循环中展开的编译时内的模板参数?

维基百科(这里)给出了一个编译时间展开for循环.......我想知道我们可以使用类似的for循环内部的模板语句...例如......

以下循环有效

template<int max_subdomain>
void Device<max_sudomain>::createSubDomains()
{
    for(int i=0; i< max_subdomain; ++i)
    {
        SubDomain<i> tmp(member);
        ...
        // some operations on tmp
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

SubDomain是一个接受模板参数int的类,这里使用一个参数构造,该参数是Device类的成员.

谢谢你的回答...现在你知道我想要什么......无论如何,我实现了我想要的?

我终于得到了我想要的..............而不是直接使用for循环......我可以使用Boost :: MPL for_each构造.我还没有实现它,但我猜这提供了一种方法来做我想要的.....

我在这里从另一个堆栈溢出问题中得到了答案...但是对同一个问题的评论谴责它的使用,因为它会非常慢(当然对于大的循环)...但是...对于不大的循环我不要认为应该有任何膨胀...我会尝试代码,让你知道结果....

在该示例中很好地说明了该用途

c++ templates loop-unrolling

6
推荐指数
2
解决办法
2518
查看次数

循环展开(使用按位运算)

我正在编写Linux内核驱动程序(用于ARM),在irq处理程序中我需要检查中断位.

bit
 0/16  End point 0 In/Out interrupt
       (very likely, while In is more likely)
 1/17  End point 1 In/Out interrupt
 ...
15/31  End point 15 In/Out interrupt
Run Code Online (Sandbox Code Playgroud)

请注意,一次可以设置多个位.

所以这是代码:

int i;
u32 intr = read_interrupt_register();

/* ep0 IN */
if(likely(intr & (1 << 0))){
    handle_ep0_in();
}

/* ep0 OUT */
if(likely(intr & (1 << 16))){
    handle_ep0_out();
}

for(i=1;i<16;++i){
    if(unlikely(intr & (1 << i))){
        handle_ep_in(i);
    }
    if(unlikely(intr & (1 << (i + 16)))){
        handle_ep_out(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

(1 << …

c bit-manipulation linux-kernel loop-unrolling

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

有没有办法用编译器在AMD OpenCL内核中展开循环?

我正在尝试评估OpenCL for AMD和Nvidia GPU之间的性能差异.我有一个执行矩阵向量乘法的内核.我现在在两个不同的系统上运行内核,我的笔记本电脑有一个带Ubuntu 12.04的NVidia GT525m和CUDA 4.0(包含OpenCL库和标题),另一个是带有Ubuntu的AMD Radeon HD7970的桌面12.04和最新的Catalyst驱动程序.

在内核中,我有两个#pragma unroll语句可以为Nvidia OpenCL实现产生大的加速(~6x).但是,AMD OpenCL版本不会产生任何加速.使用AMD APP内核分析器查看内核会出现错误,因为行程计数未知,因此未使用展开.所以我的问题是,是否#pragma unroll可以与AMD OpenCL一起使用,或者是否有替代方案(可能是我不知道的编译器标志).我已经在下面包含了内核

__kernel void mvKernel(__global float* a, const __global float* x, __global float* y, int m, int n)
{
    float sum = 0.0f;
    __global float* A;
    int i;
    int j = 0;
    int indx = get_global_id(0);
    __local float xs[12000];
#pragma unroll 
    for(i = get_local_id(0); i < n; i+= get_local_size(0)) {
        xs[i] = x[i];
    } 
    barrier(CLK_LOCAL_MEM_FENCE);
    A = &a[indx];
#pragma unroll 256
    for(i …
Run Code Online (Sandbox Code Playgroud)

compiler-construction pragma opencl loop-unrolling amd-processor

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

在叮当声中展开循环

我正在尝试有选择地展开以下程序中的第二个循环:

#include <stdio.h>

int main()
{
    int in[1000], out[1000]; 
    int i,j;

    #pragma nounroll
    for (i = 100; i < 1000; i++)
    {
       in[i]+= 10;
    }

    #pragma unroll 2
    for (j = 100; j < 1000; j++)
    {
       out[j]+= 10;
    }

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

当我使用以下选项运行 clang (3.5) 时,它会将两个循环展开 4 次。

clang -std=c++11 -O3 -fno-slp-vectorize -fno-vectorize -mllvm -unroll-count=4 -mllvm -debug-pass=Arguments -emit-llvm -c *.cpp 
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?此外,如果我添加-fno-unroll-loops或跳过-unroll-count=4标志,它不会展开任何循环。

另外,有关如何调试 pragma 错误的任何提示?

c++ optimization clang llvm-clang loop-unrolling

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

GCC 5.1循环展开

给出以下代码

#include <stdio.h>

int main(int argc, char **argv)
{
  int k = 0;
  for( k = 0; k < 20; ++k )
  {
    printf( "%d\n", k ) ;
  }
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 5.1或更高版本

-x c -std=c99 -O3 -funroll-all-loops --param max-completely-peeled-insns=1000 --param max-completely-peel-times=10000
Run Code Online (Sandbox Code Playgroud)

部分循环展开,它将循环展开十次然后进行条件跳转.

.LC0:
        .string "%d\n"
main:
        pushq   %rbx
        xorl    %ebx, %ebx
.L2:
        movl    %ebx, %esi
        movl    $.LC0, %edi
        xorl    %eax, %eax
        call    printf
        leal    1(%rbx), %esi
        movl    $.LC0, %edi
        xorl    %eax, %eax
        call    printf
        leal    2(%rbx), %esi
        movl    $.LC0, %edi …
Run Code Online (Sandbox Code Playgroud)

c gcc loops compiler-optimization loop-unrolling

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

在 x86-64 中展开循环实际上会使代码更快吗?

我想每个人都知道“展开循环意味着什么”。以防万一,我稍后会给出一个具体的例子。我要问的问题是……在 x86-64 汇编语言中展开循环实际上会使代码更快吗?我将解释为什么我开始质疑这个概念。

对于那些不熟悉“展开循环”一词的人,这里是我现在正在编写的代码中的一个循环示例:

    movq   $15, %rcx                  # rcx = loop iterations
s1024_divide_compare_loop:
    movq   (%r14, %rcx, 8), %rax      # rax = numerator
    subq   (%r15, %rcx, 8), %rax      # flags = numerator - denominator
    js     s1024_divide_done          # divide done: (numerator < denominator)
    jnz    s1024_upshift_done         # do the divide: (numerator > denominator)
    subq   $1, %rcx                   # rcx = rcx - 1 : one less loop interation
    jns    s1024_divide_compare_loop  # check next lower 64-bit portion of n & d
Run Code Online (Sandbox Code Playgroud)

这是循环展开的样子:

    movq   120(%r14), %rax …
Run Code Online (Sandbox Code Playgroud)

performance assembly caching loops loop-unrolling

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

矢量化:什么时候值得手动展开循环?

我想大致了解何时可以期望编译器对循环进行矢量化,以及何时值得我展开循环以帮助它决定使用矢量化。

我知道细节非常重要(什么编译器,什么编译选项,什么架构,如何在循环中编写代码等),但我想知道是否有一些针对现代编译器的通用指南。

我将更具体地给出一个简单循环的示例(代码不应该计算任何有用的东西):

    double *A,*B; // two arrays
    int delay = something
    [...]


    double numer = 0, denomB = 0, denomA = 0;
    for (int idxA = 0; idxA < Asize; idxA++)
    {
        int idxB = idxA + (Bsize-Asize)/2 + delay;
        numer  += A[idxA] * B[idxB];
        denomA += A[idxA] * A[idxA];
        denomB += B[idxB] * B[idxB];
    }
Run Code Online (Sandbox Code Playgroud)

我可以期望编译器对循环进行矢量化吗?或者重写如下代码是否有用?

    for ( int idxA = 0; idxA < Asize; idxA+=4 )
    {
        int idxB = idxA + (Bsize-Asize)/2 …
Run Code Online (Sandbox Code Playgroud)

c c++ vectorization loop-unrolling

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

为什么 V8 和 Spidermonkey 似乎都没有展开静态循环?

做一个小检查,它看起来既不是 V8 也不是 Spidermonkey 展开循环,即使它是完全明显的,它们是多长时间(字面作为条件,在本地声明):

const f = () => {
  let counter = 0;
  for (let i = 0; i < 100_000_000; i++) {
    counter++;
  }
  return counter;
};

const g = () => {
  let counter = 0;
  for (let i = 0; i < 10_000_000; i += 10) {
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
    counter++;
  }
  return counter;
}

let start = performance.now();
f();
let mid = performance.now();
g();
let end = performance.now(); …
Run Code Online (Sandbox Code Playgroud)

javascript v8 spidermonkey loop-unrolling

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