2011-09-22 2 views
6

a = a + b + c라고 쓰는 것이 더 효율적인 방법인지 궁금합니다.STL 추력 다중 벡터 변환?

thrust::transform(b.begin(), b.end(), c.begin(), b.begin(), thrust::plus<int>()); 
thrust::transform(a.begin(), a.end(), b.begin(), a.begin(), thrust::plus<int>()); 

이 작동하지만 한 줄의 코드를 사용하여 동일한 효과를 얻을 수있는 방법이 있나요? 예제에서 saxpy 구현을 살펴 보았으나 2 개의 벡터와 상수 값을 사용합니다.


이 방법이 더 효율적입니까?

struct arbitrary_functor 
{ 
    template <typename Tuple> 
    __host__ __device__ 
    void operator()(Tuple t) 
    { 
     // D[i] = A[i] + B[i] + C[i]; 
     thrust::get<3>(t) = thrust::get<0>(t) + thrust::get<1>(t) + thrust::get<2>(t); 
    } 
}; 


int main(){ 

    // allocate storage 
    thrust::host_vector<int> A; 
    thrust::host_vector<int> B; 
    thrust::host_vector<int> C; 

    // initialize input vectors 
    A.push_back(10); 
    B.push_back(10); 
    C.push_back(10); 

    // apply the transformation 
    thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(A.begin(), B.begin(), C.begin(), A.begin())), 
        thrust::make_zip_iterator(thrust::make_tuple(A.end(), B.end(), C.end(), A.end())), 
        arbitrary_functor()); 

    // print the output 
     std::cout << A[0] << std::endl; 

    return 0; 
} 
+0

이것은 나에게 꽤 좋아 보인다. –

답변

7

a = a + b + c 낮은 휘도 연산부 (매 4 개 메모리 동작에 대한 두 개의 산술 연산)을 가지고 있으므로, 계산은 메모리 대역폭이 따를 것이다. 제안 된 솔루션의 효율성을 비교하려면 대역폭 요구량을 측정해야합니다.

첫 번째 솔루션에서 transform을 호출 할 때마다 plus을 호출 할 때마다 두 개의로드와 한 개의 저장소가 필요합니다. 따라서 각 transform 호출의 비용을 3N으로 모델링 할 수 있습니다. 여기서 N은 벡터 a, bc의 크기입니다. transform이라는 두 번의 호출이 있으므로이 솔루션의 비용은 6N입니다.

동일한 방법으로 두 번째 솔루션 비용을 모델링 할 수 있습니다. arbitrary_functor을 호출 할 때마다 세 개의로드와 한 개의 스토어가 필요합니다. 따라서이 솔루션의 비용 모델은 4N 일 수 있습니다. 이는 을 두 번 호출하는 것보다 for_each 솔루션이 더 효율적이어야 함을 의미합니다. N이 큰 경우 두 번째 솔루션은 첫 번째 솔루션보다 빠른 6N/4N = 1.5x을 수행해야합니다.

물론 transform을 두 번 호출하지 않으므로 비슷한 방법으로 zip_iteratortransform을 결합 할 수 있습니다.

+0

매우 세련된 분석이지만 zip 반복기가 얼마나 비싸다는 것을 궁금하게 생각할 수는 없습니다. (나는 그것을 많이 사용하지만 작동 방식이나 성능에 대한 느낌이 없습니다.) 여기에 어떤 영향이 있습니까? – talonmies

+0

zip_iterator는 실제로 각 Zip 반복기가 레지스터 리소스를 필요로하므로 커널의 공간을 늘릴 수 있습니다. 이 예에서 A는 zip에 중복 적으로 포함됩니다. 한 번은 소스로, 한 번은 대상으로 사용됩니다. 약간 더 마른 솔루션은 zip으로 한번만 전송할 수 있지만 arbitary_functor가 매우 간단하다는 점을 고려하면 차이를 만들 가능성은 거의 없습니다. –

관련 문제