我刚刚阅读了 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)
这会通过以下方式更改输出程序集:
这会显着降低吞吐量性能。
为什么 64 位 HotSpot VM 不为long计数器执行循环展开?为什么第二种情况需要安全点,而第一种情况不需要?
我正在尝试使用模板在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
维基百科(这里)给出了一个编译时间展开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构造.我还没有实现它,但我猜这提供了一种方法来做我想要的.....
我在这里从另一个堆栈溢出问题中得到了答案...但是对同一个问题的评论谴责它的使用,因为它会非常慢(当然对于大的循环)...但是...对于不大的循环我不要认为应该有任何膨胀...我会尝试代码,让你知道结果....
在该示例中很好地说明了该用途
我正在编写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 << …
我正在尝试评估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
我正在尝试有选择地展开以下程序中的第二个循环:
#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 错误的任何提示?
给出以下代码
#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) 我想每个人都知道“展开循环意味着什么”。以防万一,我稍后会给出一个具体的例子。我要问的问题是……在 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) 我想大致了解何时可以期望编译器对循环进行矢量化,以及何时值得我展开循环以帮助它决定使用矢量化。
我知道细节非常重要(什么编译器,什么编译选项,什么架构,如何在循环中编写代码等),但我想知道是否有一些针对现代编译器的通用指南。
我将更具体地给出一个简单循环的示例(代码不应该计算任何有用的东西):
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) 做一个小检查,它看起来既不是 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)loop-unrolling ×10
c++ ×4
c ×3
loops ×2
templates ×2
assembly ×1
caching ×1
clang ×1
gcc ×1
java ×1
javascript ×1
jit ×1
jvm-hotspot ×1
linux-kernel ×1
llvm-clang ×1
opencl ×1
optimization ×1
performance ×1
pragma ×1
spidermonkey ×1
v8 ×1