繁体   English   中英

我可以在并行执行策略中使用 std::transform 吗?

[英]Can I use std::transform in place with a parallel execution policy?

如果我没记错的话,我可以通过使用与输入相同的范围和 output 迭代器来使std::transform就地执行。 假设我有一些std::vector object vec ,那么我会写

std::transform(vec.cbegin(),vec.cend(),vec.begin(),unary_op)

使用合适的一元运算unary_op

使用 C++17 标准,我想通过在其中粘贴std::execution::par作为第一个参数来并行执行转换。 这将使std::transform上的 cppreference 文章中的 function go 从过载 (1) 变为 (2)。 然而,对此重载的评论说:

unary_op [...] 不得使任何迭代器无效,包括结束迭代器,或修改所涉及范围的任何元素。 (C++11 起)

“修改任何元素”是否真的意味着我不能在适当的位置使用算法,或者这是在谈论我误解的不同细节?

我相信它在谈论一个不同的细节。 unary_op获取序列的一个元素并返回一个值。 该值(通过transform )存储到目标序列中。

所以这个unary_op就可以了:

int times2(int v) { return 2*v; }

但这个不会:

int times2(int &v) { return v*=2; }

但这并不是你真正要问的。 您想知道是否可以将transformunary_op版本用作具有相同源和目标范围的并行算法。 我不明白为什么不。 transform将源序列的单个元素映射到目标序列的单个元素。 但是,如果您的unary_op不是真正的一元,(即,它引用序列中的其他元素 - 即使它只读取它们,那么您将有数据竞争)。

在这里引用标准

[alg.transform.1]

op [...] 不应使迭代器或子范围无效,或修改范围中的元素

这禁止您的unary_op修改作为参数给出的值或容器本身。

auto unary_op = [](auto& value) 
{ 
    value = 10;    // this is bad
    return value;
}

auto unary_op = [&vec](auto const& value) 
{ 
    vec[0] = value;   // also bad
    return value;
}

auto unary_op = [&vec](auto& value) 
{ 
    vec.erase(vec.begin());   // nope 
    return value;
}

但是,以下是可以的。

auto unary_op = [](auto& value)  // const/ref not strictly needed
{         
    return value + 10;   // totally fine
}

auto unary_op = [&vec](auto& value)
{         
    return value + vec[0];   // ok in sequential but not in parallel execution
}

独立于我们拥有的UnaryOperation

[alg.transform.5]

在一元变换的情况下,结果可能等于第一个 [...]。

意味着明确允许就地操作。

现在

[算法.parallel.overloads.2]

除非另有说明,否则 ExecutionPolicy 算法重载的语义与其没有的重载相同。

意味着执行策略在算法上没有用户可见的差异。 您可以期望该算法产生完全相同的结果,就像您不指定执行策略一样。

正如您在引用的链接示例中所见,修改任何元素并不意味着对元素进行所有类型的修改:

function 的签名应该等同于以下内容:

 Ret fun(const Type &a);

这包括对元素的修改。 在最坏的情况下,如果您对目标使用相同的迭代器,则修改不应导致迭代器失效,例如push_back到 vector 或从vector eras可能会导致迭代器失效。

看一个你不应该做的失败例子Live

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM