C3015:OpenMP 'for' 语句中的初始化格式不正确

Posted

技术标签:

【中文标题】C3015:OpenMP \'for\' 语句中的初始化格式不正确【英文标题】:C3015: initialization in OpenMP 'for' statement has improper formC3015:OpenMP 'for' 语句中的初始化格式不正确 【发布时间】:2016-08-14 10:07:28 【问题描述】:

我有并行扫描算法:Hillis & Steele (1986),我想并行执行内部 for 循环。

Error   C3015   initialization in OpenMP 'for' statement has improper form  OpenMP  c:\users\matja\documents\visual studio 2015\projects\psseminar\openmp\main.c

我以前从未遇到过这个错误,我用谷歌搜索过,但没有发现任何有用的东西。

包括:

#include <omp.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <limits.h>
#include <windows.h>

代码块:

// ...
for (long long m = 0; m < M; m++)

    long long offset = (long long)pow(2, m);

    #pragma omp parallel for firstprivate(N, m, offset)
    for (long long n = offset; n < N; n++)
    
        long long ai = n - offset;
        long long bi = n;
        // ...
    

// ...

【问题讨论】:

【参考方案1】:

根据 MSDN,当 OpenMP 未完全明确时,会引发 OP 发布的错误。这可能是因为编译器没有完全理解语句使用的 C99 语言

for (long long n = offset; n < N; n++)

尽管我没有 Visual C++ 编译器,但我发现 gcc 4.8.5 和 icc 16.0.3 无法编译它,需要使用适当的 C99 语言变体(即-std=c99)编译代码。在谷歌搜索了一下之后,我没有找到适合 MSVC 的标志(事实上,***声称支持 ins MSVC 2013 是有限的(参见https://en.wikipedia.org/wiki/C99))。因此,您可以尝试的一种替代方法是将代码转换为

long long m;

for (m = 0; m < M; m++)

    long long offset = (long long)pow(2, m);
    long long n;

    #pragma omp parallel for firstprivate(N, m, offset)
    for (n = offset; n < N; n++)
    
        long long ai = n - offset;
        long long bi = n;
        // ...
    

另外,请注意,如果您不在并行循环中修改,您可能可以去掉 Nmoffsetfirstprivate 子句并将它们更改为 shared

顺便说一句,我不同意 tahini 的回答,他们声称 #pragma omp parallel for 仅限于 intunsigned int,因为以下代码在 gcc 4.8.5 和 icc 16.0.3 中都能完美运行。

#include <omp.h>
#include <stdio.h>
void main (void)

    long long m;

    #pragma omp parallel for schedule
    for (m = 0; m < 16; m++)
    
            printf ("thread = %d, m = %d\n", omp_get_thread_num(), m);
    

【讨论】:

【参考方案2】:

omp parallel for 中的迭代变量被限制为 int 或 unsigned int。 long long 不是有效的迭代器类型。

https://computing.llnl.gov/tutorials/openMP/#ParallelRegion

【讨论】:

我希望 int64_t 在合适的平台上工作,但我认为这不是可移植的期望。即使它可以工作,但在没有硬件支持的平台上它可能会很慢。 您可能想比较并行的内循环或外循环是否更快。有些人还使用 SIMD,测试多种方法很常见。 这个答案不正确。只需检查来自OpenMP 4.0 examples 的示例编号 29。 MSVC 不支持超过 2.0 的 OpenMP,它在 C(这里限制为 C89)和 C++ 之间做出了区分。在 VS2017 中似乎有更多的 C89 支持,但这个痛苦的问题仍然存在。 VS2019 也有同样的问题。必须使用 C89 变量声明,即使是 int。

以上是关于C3015:OpenMP 'for' 语句中的初始化格式不正确的主要内容,如果未能解决你的问题,请参考以下文章

openmp 条件并行循环

我如何理解我在 openMP 中的代码?

非for循环的OpenMP并行化

如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?

OpenMP的主要功能,基本构成体都有哪些

OpenMP 中的同步