并行执行策略是否要求迭代器引用类型为左值?

问题描述 投票:0回答:1

我在代码中发现了一个性能问题,该问题是由于在非左值范围上使用并行执行策略调用的算法缺乏并行性而导致的。

请考虑以下说明该行为的代码:

#include <chrono>
#include <iostream>
#include <thread>
#include <algorithm>
#include <execution>
#include <ranges>

#include <tbb/parallel_for.h>

struct Timer {
    Timer() : start{std::chrono::high_resolution_clock::now()} {}
    ~Timer() {
        auto stop = std::chrono::high_resolution_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start) << '\n';
    }
    std::chrono::time_point<std::chrono::high_resolution_clock> start;
};

auto fn    = [](int) {
    using namespace std::chrono_literals;
    std::this_thread::sleep_for(1ms);
};

void run(std::ranges::range auto&& rng) {
    Timer timer;
    std::for_each(std::execution::par, rng.begin(), rng.end(), fn);
}

int main() {
    constexpr int N = 200;
    run(std::views::iota(0, N));                                                                // not parallel
    run(std::array<int, N>{});                                                                  // parallel
    run(std::array<int, N>{} | std::views::transform([](auto& elem) { return elem * 2; }));     // not parallel
    run(std::array<int, N>{} | std::views::transform([](auto& elem) -> int& { return elem; })); // parallel
    {
        Timer timer;
        tbb::parallel_for(0, N, fn);                                                            // parallel
    }
    return 0;
}

假设并行函数只需要 const 访问(这很常见),第三种情况似乎有限制。 标准是否要求这种行为?

c++ parallel-processing c++17 std
1个回答
0
投票

在 C++17 和 C++20 中是这样,但从 C++23 开始不是这样。从技术上讲,您的调用在 C++23 之前是不正确的,因为您违反了库函数先决条件。

C++17 的措辞

如果算法的模板参数名为

ForwardIterator
ForwardIterator1
ForwardIterator2
,则模板参数应满足前向迭代器的要求。

类或指针类型 X 满足前向迭代器的要求,如果

  • 如果 X 是可变迭代器,则引用是对 T 的引用;如果 X 是常量迭代器,则引用是对 const T 的引用

C++20 的措辞

如果算法的模板参数名为

ForwardIterator
ForwardIterator1
ForwardIterator2
,则模板参数应满足 Cpp17ForwardIterator 要求

类或指针类型 X 满足前向迭代器的要求,如果

  • 如果 X 是可变迭代器,则引用是对 T 的引用;如果 X 是常量迭代器,则引用是对 const T 的引用

C++23 的措辞

如果算法的模板参数名为

ForwardIterator
ForwardIterator1
ForwardIterator2
NoThrowForwardIterator
,并且要求模板参数是可变迭代器或模型,则模板参数应满足 Cpp17ForwardIterator 要求
forward_iterator
否则。

© www.soinside.com 2019 - 2024. All rights reserved.