std::转换和连续内存

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

我需要一个 lambda,将(负)离散拉普拉斯运算符(矩阵)应用于连续的内存容器(向量),如

std::array
std::vector

使用

std::transform
这样递增和递减指针来编写它会是未定义的行为吗?

  auto A = [n,&h2](const auto & in, auto & out)
  {
    // First line of the matrix
    out[0] = (2.*in[0] - in[1])/h2 ;
    // Middle lines of the matrix
    std::transform(std::execution::par_unseq,
                   std::next(in.cbegin()),std::next(in.cend(),-1),std::next(out.begin()),
                   [&h2](const auto & val)
                   {
                     return (-*(std::next(&val,-1)) + 2.*val - *(std::next(&val)))/h2;
                   });
    // Final line of the matrix
    out[n-1] = (-in[n-2] + 2.*in[n-1])/h2;
  };

换句话说,像

for_each
transform
这样的算法以及其他并行算法是否会破坏某些执行策略的连续内存?

编辑1:请注意,我不关心我首先处理向量

in
的哪个元素,我关心的是当我在
*std::next(&val)
中的lambda内执行
std::transform
时,我是否获得了下一个向量
in
中的元素,而不是未定义的元素。

编辑2:我正在考虑一些策略,这些策略意味着将值复制到其他地方(例如SIMD寄存器)并在返回结果之前在那里执行lambda。标准中的执行策略或并行算法是否存在阻止这种情况发生的条件?

c++ multithreading std execution
1个回答
0
投票

不,这不安全 [algorithms.parallel.exec]p3

除非另有说明,实现可以从

T
is_trivially_copy_constructible_v<T>
为 true 的序列中任意复制元素(类型为
is_trivially_destructible_v<T>
)。

注释中给出的解决方案是包装迭代器:

auto ref_view = in | std::views::transform([](const auto& i) { return std::cref(i); });
std::transform(std::execution::par_unseq,
      std::next(ref_view.begin()),std::prev(ref_view.end()),std::next(out.begin()),
      [&h2](auto ref)
      {
        const auto& val = ref.get();
        return (-*(std::next(&val,-1)) + 2.*val - *(std::next(&val)))/h2;
      });
© www.soinside.com 2019 - 2024. All rights reserved.