2015-01-29 6 views
0

David Vandevoorde의 "C++ Template"책과 비슷한 표현식 템플릿을 프로파일 링하려고합니다. 아래는 예상치 못한 결과를 보여주기 때문에 이론적 인 분석입니다. 시험은 약 가정 : A, B, C, R은 힙에 할당 배열 인프로파일 링 표현식 템플릿

R = A + B + C; 

. 배열의 크기는 2입니다. 따라서 다음 명령이 실행됩니다.

대략 12 명령 (각각 6 개).

: 식 템플릿 (매우 하단에 도시)을 사용하는 경우 형 공제 컴파일시에 실시 된 후, 동일한 평가가 상술 한 바와 같이 수행하기 전에

이제, 다음의 실행시에 처리 될

A + B --> expression 1 // copy references to A & B 
expression 1 + C --> expression 2 // copy the copies of references to A & B 
            // + copy reference to C 

따라서 전체 명령의 약 5/(5 + 12) = 30 % 인 평가 전 총 2 + 3 = 5 명령이 있습니다. 그래서 나는 특히 벡터 크기가 작을 때이 오버 헤드를 볼 수 있어야합니다.

그러나 두 결과는 거의 같습니다. 나는 1E + 09 번 시험을 반복한다. 물론 둘의 어셈블리 코드는 동일합니다. 그러나 나는이 "건설"부분을 위해 시간이나 지시를 요하는 부분을 찾을 수 없었다.

movsdq (%r9,%rax,8), %xmm0 
addsdq (%r8,%rax,8), %xmm0 
addsdq (%rdi,%rax,8), %xmm0 
movsdq %xmm0, (%rcx,%rax,8) 

저는 CS 배경이 좋지 않으므로이 질문이 너무 어리석 수 있습니다. 그러나 나는 이것에 대해 며칠 동안 머리를 긁적 거렸다. 그래서 어떤 도움을 얻을 수 있습니다!

--- 내 표현 템플릿 --- 특성은 객체의 참조의 값을주의해야한다 여부를 결정하는 것 외에 아무것도하지 않는

template< typename Left, typename Right > 
class V_p_W // stands for V+W 
{ 
public: 
    typedef typename array_type::value_type    value_type; 
    typedef double          S_type; 
    typedef typename traits<Left>::type    V_type; 
    typedef typename traits<Right>::type    W_type; 

    V_p_W (const Left& _v, const Right& _w) : V(_v), W(_w) 
    {} 

    inline value_type operator [] (std::size_t i)  { return V[i] + W[i]; } 
    inline value_type operator [] (std::size_t i) const { return V[i] + W[i]; } 
    inline std::size_t size() const      { return V.size(); } 

private: 
    V_type V; 
    W_type W; 
}; 

. 예를 들어, 값은 정수에는 복사되지만 배열에 대해서는 참조가 사용됩니다.

+0

내가 누락되었을 수도 있지만 "the"표현 템플릿은 무엇입니까? 당신이 어떤 도서관을 추측하고있는 것 같지만, 어떤 추측이 완전히 임의적인지 알지 못한다면. 그럼에도 불구하고 표현식 템플릿을 실제 값에 할당하면 ('R'은 힙에 배열이 있어야합니다), 당연히 해결되어야합니다 ... –

+0

@ gha.st 그 책 "C++ Template".내 질문을 업데이트 할게. 감사! BTW, "해결 된"이라고 말하면 무엇을 의미합니까? – user3156285

+1

작업을 실제로 수행해야합니다. 'R [0]'을 올바르게하려면, A [0] + B [0] + C [0]'을 수행 할 필요가 있으며, 2 개의 피연산자를 더한 경우에는 2 개의 덧셈 만이 유일한 합리적인 방법입니다 그것을 할! 그리고 그것은 솔직히 말해서 그 추가가 어떻게 일어나게 될지 최소한 중요하지 않습니다. –

답변

0

나의 가정 양조 시험. 이상적으로 표현 템플릿은 순진한 경우 임시 벡터에 필요한 추가 할당을 저장합니다.

expr.cpp :

#include <vector> 
#include <stdlib.h> 
#include <iostream> 
#include <ctime> 

using namespace std; 

typedef vector<int> Valarray; 

template<typename L, typename R> 
struct BinOpPlus { 
    const L& left; 
    const R& right; 

    BinOpPlus(const L& l, const R& r) 
    : left(l), right(r) 
    {} 

    int operator[](int i) const { return left[i] + right[i]; } 
}; 

template<typename L, typename R> 
BinOpPlus<L, R> operator+(const L& left, const R& right){ 
    return BinOpPlus<L, R>(left, right); 
} 

int main() { 
    int size = 10000000; 
    Valarray v[3]; 
    for(int n=0; n<3; ++n){ 
    for(int i=0; i<size; ++i){ 
     int val = rand() % 100; 
     v[n].push_back(val); 
    } 
    } 

    std::clock_t start = std::clock(); 
    auto tmp = v[0] + v[1]; 
    auto out = tmp + v[2]; 

    int sum = 0; 
    for(int i=0; i<size; ++i) 
    sum += out[i]; 

    std::clock_t stop = std::clock(); 
    cout << "Sum: " << sum << endl; 
    cout << "Time: " << (stop-start) << endl; 
    return 0; 
} 

vala.cpp :

#include <vector> 
#include <stdlib.h> 
#include <iostream> 
#include <ctime> 

using namespace std; 

class Valarray : public vector<int> { 
    public: 
    Valarray operator+(const Valarray& r) const { 
     Valarray out; 
     out.reserve(r.size()); 
     for(size_t i=0; i<r.size(); ++i) 
     out.push_back((*this)[i] + r[i]); 
     return out; 
    } 

    Valarray operator+(Valarray&& r) const { 
     for(size_t i=0; i<r.size(); ++i) 
     r[i] = (*this)[i] + r[i]; 
     return r; 
    } 
}; 

int main() { 
    int size = 10000000; 
    Valarray v[3]; 
    for(int n=0; n<3; ++n){ 
    for(int i=0; i<size; ++i){ 
     int val = rand() % 100; 
     v[n].push_back(val); 
    } 
    } 

    std::clock_t start = std::clock(); 
    Valarray out = v[0] + v[1] + v[2]; 

    int sum = 0; 
    for(int i=0; i<size; ++i) 
    sum += out[i]; 

    std::clock_t stop = std::clock(); 
    cout << "Sum: " << sum << endl; 
    cout << "Time: " << (stop-start) << endl; 
    return 0; 
} 

명령 행 : 최적화와

g++ -Wfatal-errors -std=c++11 -Wall -Werror vala.cpp -o vala 
g++ -Wfatal-errors -std=c++11 -Wall -Werror expr.cpp -o expr 
~/example$ ./vala 
Sum: 1485274472 
Time: 680000 
~/example$ ./expr 
Sum: 1485274472 
Time: 130000 

:

g++ -Wfatal-errors -std=c++11 -Wall -Werror vala.cpp -o vala -O3 
g++ -Wfatal-errors -std=c++11 -Wall -Werror expr.cpp -o expr -O3 
na:~/example$ ./vala 
Sum: 1485274472 
Time: 290000 
na:~/example$ ./expr 
Sum: 1485274472 
Time: 10000 
,

여분의 벡터 할당을 피하기 때문에 표현 템플릿을 크게 개선했습니다.