【问题标题】:How do I Auto-Parallelize Heap Arrays?如何自动并行化堆数组?
【发布时间】:2019-01-14 19:41:39
【问题描述】:

我正在尝试编写一个函数,将堆上的数组乘以一个常数,使用并行 for 循环,但是当尝试在 VisualStudio 2017 中使用 /Qpar-report:2 集进行编译时,我收到消息“由于原因“1000”,循环未并行化。我查了一下,消息是“编译器检测到循环体中的数据依赖关系。”:

https://docs.microsoft.com/en-us/cpp/error-messages/tool-errors/vectorizer-and-parallelizer-messages?view=vs-2017#BKMK_ReasonCode100x

文本描述了(例如)不同的传递依赖于其他传递的结果的情况,但这并不适用于此。我能想到的唯一情况是优化器可能会担心两个数组在内存中重叠,但是你如何说服编译器不是这种情况呢?

我尝试使用#pragma ivdep 语句强制它并且代码编译但函数在被调用时挂起。

经过多次故障排除,我确定如果我在函数内部的堆栈上创建虚拟数组并循环遍历它们,它就会成功并行化。不幸的是,我不能依赖我将接受的数组小到可以完全复制到堆栈中。

我查看了 SO 和 google 以获取其他并行执行类似这样的简单数组操作的示例,它们都使用堆栈分配的数组。肯定有一种干净的方法可以并行化堆数组上的操作??

#include "stdafx.h"
#include "CppUnitTest.h"
#include "../UnitsConversion/UnitsConversion.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

#define ARRAY_SIZE 10000000

double* testInD;
double* testOutD;

namespace UnitTest
{

TEST_CLASS(Parallel)
{
public:

    TEST_CLASS_INITIALIZE(setup) {
        testInD = new double[ARRAY_SIZE];
        testOutD = new double[ARRAY_SIZE];

        for (int i = 0; i < ARRAY_SIZE; i++) {
            testInD[i] = (double)rand() / (double)RAND_MAX;
            testOutD[i] = (double)rand() / (double)RAND_MAX;
        }

    }

    TEST_CLASS_CLEANUP(cleanup) {
        delete testInD;
        delete testOutD;
    }

    TEST_METHOD(PressuresD)
    {
        Assert::AreEqual(
            (int)1,
            PressureD(
                testInD,
                testOutD,
                ARRAY_SIZE
            )
        );
    }

}

int __stdcall PressureD(
    double* dblInValue,
    double* dblOutValue,
    int n) {

#pragma loop(hint_parallel(0))
    for (int i = 0; i < n; ++i) {
    dblOutValue[i] = dblInValue[i] * 5.0;
    }

    return 1;
}

无论出于何种原因,我都无法通过 Google 或 SO 找到解决方案,尽管我认为这将是一个常见问题。我错过了什么吗?

编辑:

将循环更改为以下确实允许它并行化:

for (int i = 0; i < n; ++i) {
    //dblOutValue[i] = dblInValue[i] * factor; (old version)
    dblOutValue[i] *= factor;
}

但是,当我尝试运行单元测试时,代码挂起并最终(大约 15 秒后)中止。当我在调试模式下运行代码时,它可以工作,但我 95% 确定这是因为在调试模式下运行时它没有并行化。

【问题讨论】:

  • 你试过__restrict吗?
  • 我没听说过这个关键字!我试过了,代码在编译时确实并行化了,但是当我运行它时,单元测试仍然挂起并最终中止。

标签: c++ visual-studio performance parallel-processing x86


【解决方案1】:

这是一个简单的新建/删除不匹配。您的单元测试有数组 new[] 和标量 delete

放弃手动内存管理并使用std::unique_ptr&lt;double[]&gt;std::vector&lt;double&gt;。您可能需要在循环之前获取指向数据的裸指针(事实上,PressureD 根本不需要更改),以便并行化成功,但您不需要手动管理生命周期。

【讨论】:

  • 感谢您提供有关使用向量的提示。我尝试将数组声明换成std::vector&lt;double&gt; testInD(ARRAY_SIZE);,并将函数调用中的指针换成&amp;testInD[0],但测试仍在中止。
  • @Porksodaguy:好的,是时候调试优化(又名发布)构建了
猜你喜欢
  • 2012-06-03
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多