#pragma block_loop
适用的调用
| 编译指示 (pragma) | xlc (编译 C) | xlC (编译 C++) | xlclang(编译 C) | xlclang++(编译 C++) |
|---|---|---|---|---|
#pragma block_loop |
✓ | ✓ |
注: 此表中仅列出典型调用。 对于所有基本调用及其等效特殊调用,您可以参阅 编译器调用的完整列表 。
类别
用途
使用特定于作用域的标识来标记块。
语法
参数
- expression
- 表示迭代组大小的整数表达式。
- 名称
- 作用域限定单元中唯一的标识。 如果未指定 name,那么在 #pragma block_loop 伪指令之后的第一个
for循环或循环上将发生分块。
使用量
要使循环阻塞发生, #pragma block_loop 伪指令必须在 for 循环之前。
如果对阻塞循环指定 #pragma unroll, #pragma unrollandfuse 或 #pragma stream_unroll ,那么如果实际创建了阻塞循环,那么将分别对阻塞循环进行解滚,解滚和融合或流解滚。 否则,此伪指令无效。
如果为阻塞循环指定 #pragma unrollandfuse, #pragma unroll 或 #pragma stream_unroll 伪指令,那么在创建阻塞循环之后,该伪指令将应用于阻塞循环。 如果未创建阻塞循环,那么此伪指令将应用于用于阻塞的循环,就像未指定相应的 #pragma block_loop 伪指令一样。
不得多次指定 #pragma block_loop ,也不得将该伪指令与 #pragma nounroll, #pragma unroll, #pragma nounrollandfuse, #pragma unrollandfuse或 #pragma stream_unroll 伪指令组合到同一 for 循环中。 此外,不应将多个 #pragma unroll 伪指令应用于单个块循环伪指令。
始终先完成所有 #pragma block_loop 伪指令的处理,然后再执行由任何解滚伪指令指示的任何解滚
示例
以下两个示例显示了如何使用 #pragma block_loop 和 #pragma loop_id 进行循环分层:
#pragma block_loop(50, mymainloop)
#pragma block_loop(20, myfirstloop, mysecondloop)
#pragma loopid(mymainloop)
for (i=0; i < n; i++)
{
#pragma loopid(myfirstloop)
for (j=0; j < m; j++)
{
#pragma loopid(mysecondloop)
for (k=0; k < m; k++)
{
...
}
}
}
#pragma block_loop(50, mymainloop)
#pragma block_loop(20, myfirstloop, mysecondloop)
#pragma loopid(mymainloop)
for (i=0; i < n; n++)
{
#pragma loopid(myfirstloop)
for (j=0; j < m; j++)
{
#pragma loopid(mysecondloop)
for (k=0; k < m; k++)
{
...
}
}
}
以下示例显示了如何使用 #pragma block_loop 和 #pragma loop_id 进行循环交换。
for (i=0; i < n; i++)
{
for (j=0; j < n; j++)
{
#pragma block_loop(1,myloop1)
for (k=0; k < m; k++)
{
#pragma loopid(myloop1)
for (l=0; l < m; l++)
{
...
}
}
}
}
以下示例显示如何使用 #pragma block_loop 和 #pragma loop_id for loop tiling for 多级内存层次结构:
#pragma block_loop(l3factor, first_level_blocking)
for (i=0; i < n; i++)
{
#pragma loopid(first_level_blocking)
#pragma block_loop(l2factor, inner_space)
for (j=0; j < n; j++)
{
#pragma loopid(inner_space)
for (k=0; k < m; k++)
{
for (l=0; l < m; l++)
{
...
}
}
}
}
以下示例使用 #pragma unrollandfuse 和 #pragma block_loop 来解滚和融合阻塞循环。
#pragma unrollandfuse
#pragma block_loop(10)
for (i = 0; i < N; ++i) {
}
在这种情况下,如果忽略 block loop 伪指令,那么 unroll 伪指令没有任何作用。以下示例显示了如何使用 #pragma unroll 和 #pragma block_loop 来取消滚动阻塞的循环。
#pragma block_loop(10)
#pragma unroll(2)
for (i = 0; i < N; ++i) {
}
在这种情况下,如果忽略 block loop 伪指令,那么 unblocked 循环仍会进行解滚。 如果发生分块,那么会将 unroll 伪指令应用于分块循环。以下示例显示了该伪指令的无效用法。 第一个示例显示在未定义的循环标识上使用的 #pragma block_loop :
#pragma block_loop(50, myloop)
for (i=0; i < n; i++)
{
}
不允许引用 myloop ,因为它不在嵌套中并且可能未定义。在以下示例中,不允许引用
myloop ,因为它不在同一循环嵌套中: for (i=0; i < n; i++)
{
#pragma loopid(myLoop)
for (j=0; j < i; j++)
{
...
}
}
#pragma block_loop(myLoop)
for (i=0; i < n; i++)
{
...
}
由于 unroll 伪指令相互冲突,因此以下示例无效:
#pragma unrollandfuse(5)
#pragma unroll(2)
#pragma block_loop(10)
for (i = 0; i < N; ++i) {
}
#pragma block_loop(10)
#pragma unroll(5)
#pragma unroll(10)
for (i = 0; i < N; ++i) {
}