병렬 실행 정책으로 std :: transform을 대신 사용할 수 있습니까?


11

I 착각하지 않다, 내가 수 std::transform수행 장소에서 입출력 반복자 같은 범위를 사용하여. std::vector객체 가 있다고 가정 vec하면 쓸 것입니다.

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

적절한 단항 연산 사용 unary_op.

C ++ 17 표준을 사용하여 std::execution::par첫 번째 인수로 in 을 붙여서 변환을 병렬로 실행하고 싶습니다 . 이렇게하면의 cppreference 기사에서std::transform 함수가 과부하 (1)에서 (2)로 이동합니다 . 그러나이 과부하에 대한 의견은 다음과 같습니다.

unary_op[...]는 최종 반복자를 포함하여 반복기를 무효화하거나 관련된 범위의 요소를 수정해서는 안됩니다. (C ++ 11부터)

"요소 수정"은 실제로 알고리즘을 사용할 수 없거나 잘못 해석 한 다른 세부 사항에 대해 말하는 것입니까?

답변:


4

여기에 표준을 인용하려면

[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]

단항 변환 [...]의 경우 결과는 첫 번째와 같을 수 있습니다.

내부 작업이 명시 적으로 허용됨을 의미합니다.

지금

[algorithms.parallel.overloads.2]

달리 명시되지 않는 한, ExecutionPolicy 알고리즘 과부하의 의미는 과부하가없는 것과 동일합니다.

실행 정책에는 알고리즘에서 사용자에게 눈에 띄는 차이가 없음을 의미합니다. 알고리즘이 실행 정책을 지정하지 않은 것과 동일한 결과를 산출 할 것으로 예상 할 수 있습니다.


6

나는 그것이 다른 세부 사항에 대해 이야기하고 있다고 생각합니다. 는 unary_op시퀀스의 요소에 소요 값을 반환한다. 해당 값은 transform대상 시퀀스 에 (by ) 저장됩니다 .

그래서 이것은 unary_op좋을 것입니다 :

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

그러나 이것은하지 않을 것입니다 :

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

그러나 그것은 실제로 당신이 요구하는 것이 아닙니다. 소스 및 대상 범위가 동일한 병렬 알고리즘으로 unary_op버전을 사용할 수 있는지 알고 싶습니다 transform. 왜 그런지 모르겠습니다. transform소스 시퀀스의 단일 요소를 대상 시퀀스의 단일 요소에 매핑합니다. 그러나 unary_op실제로 단항이 아닌 경우 (즉, 시퀀스의 다른 요소를 참조하지만 읽기 만하더라도 데이터 레이스가 발생합니다).


1

언급 한 링크의 예에서 볼 수 있듯이 요소 를 수정한다고해서 요소에 대한 모든 유형의 수정이 의미하는 것은 아닙니다 .

함수의 서명은 다음과 같아야합니다.

Ret fun(const Type &a);

여기에는 요소 수정이 포함됩니다. 최악의 경우 대상에 동일한 반복자를 사용하는 경우 수정을 통해 반복자 무효화를 유발하는 push_backto 벡터 또는 erasing 등 의 반복자를 무효화하지 않아야 vector합니다.

SHOULD N'T Live 로 실패한 예를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.