c++ - 如何自动并行化堆数组?

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

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

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

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

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

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

我在 SO 和谷歌上查了其他并行执行简单数组操作的示例,它们都使用堆栈分配的数组。肯定有一种干净的方法来并行化堆数组上的操作??

#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 秒后)中止。当我在 Debug模式下运行代码时,它可以工作,但我 95% 确定那是因为它在 Debug模式下运行时没有并行化。

最佳答案

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

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

关于c++ - 如何自动并行化堆数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54188105/

相关文章:

c++ - bcp_init rturns 访问冲突

c++ - 在 Cython 中优雅地包装模板化对象

header 中缺少 C++ ODBC SQL_ATTR_PARAMS_STATUS_PTR

Java:如何以极高的性能进行基于位置 (x,y) 的索引?

java - 如何使用 Java/Android 正确测量下载速度

c++ - 将循环转换为数学方程

c++ - 是否允许在 Base 的实例上编写 Derived 的实例?

c++ - 错误 "Cannot open include file",但它不包含在代码中

c# - 数据库中没有发生数据插入

c# - 配置 ReSharper 只为非原始类型推荐 `var`?