2017-10-26 13 views
2

이것은 매우 간단한 패턴이므로이를 정렬하는 "좋은"방법이 있어야합니다.엄격한 앨리어스를 깨지 않고 바이트 버퍼를 효율적으로 생성

나는 산술 데이터가 들어있는 동적 크기의 바이트 배열을 생성해야하는 함수가 있습니다. 내가 템플릿을 dispatch() 할 수 있으며, 최악에서 see on godbolt

,하지만 매우 될 것입니다 :

// Given that I have a function that kinda looks like this: 
void dispatch(std::vector<char> data); //Will take possesion of data. 

// The behavior I want, but this breaks strict aliasing 
void bad_foo(int c) { 
    std::vector<char> real_data(c * sizeof(float)); 
    float* raw_data = reinterpret_cast<float*>(real_data.data()); 

    //Fill raw_data with usefull stuff... 

    dispatch(std::move(real_data)); 
} 

void correct_but_slow_foo(int c) { 
    std::vector<float> raw_data(c); 

    //Fill raw_data with usefull stuff... 

    std::vector<char> real_data(c * sizeof(float)); 
    std::memcpy(real_data.data(), raw_data.data(), c * sizeof(float)); 

    dispatch(std::move(real_data)); 
} 

불행하게도, 심지어는 그 소리의 힙 생략 여기 수행에 필요한 사항을 분류하는 관리되지 않는 것 같다 지저분 해, 나는이 난장판에서 탈출구가 있는지를 궁금해. 어쨌든 나는 바라보고있다.

감사합니다.

편집 : A는 단지 (즉시 물론 질문을 ... 게시 후) 내 마음을 넘어 생각 : 나는 그것의 상단에있는 연산 데이터 할당 풀로하고 자리에서 새로운 real_data을 처리 할 수 ​​:

void fixed_foo(int c) { 
    std::vector<char> real_data(c * sizeof(float)); 
    float* raw_data = new (real_data.data()) float[c]; 

    //Fill raw_data with usefull stuff... 

    dispatch(std::move(real_data)); 
} 

이것은 지옥처럼 보이지만 나는 그것이 합법적이라고 생각합니다. 아마도?

+0

'데이터'로 '디스패치'할 것은 무엇입니까? 'float' 또는'char'로 접근하면 아무 문제 없습니다. – geza

+0

@geza 'bad_foo()'는 데이터가 어떤 디스패치와 관련이 있는지는 중요하지 않습니다. – Frank

+0

그게 사실인지 모르겠습니다. 그 메모리는'float'로만 액세스 할 수 있습니다. 정말 엄격한 앨리어싱 규칙을 위반합니까? (나는 회의적 일 뿐이다.) – geza

답변

2

앨리어싱 규칙을 벗어나는 가장 안전한 방법은 memcpy()을 사용하는 것이지만 데이터의 전체 사본에서 수행 할 필요는 없습니다. 나는 당신의 float 일을 지역별 float 변수에 대해 수행 한 다음 memcpy()을 적절한 위치에 두어 한 번에 한 요소 씩 real_data 버퍼를 제안 할 것입니다. 대부분의 컴파일러는 내 경험에 따라이를 효과적으로 최적화 할 것입니다.

void better_foo(int c) { 
    std::vector<char> real_data(c * sizeof(float)); 

    //Fill raw_data with usefull stuff... 
    for (int i = 0; i < c; ++i) { 
    float x = my_complicated_calculation(i); 
    memcpy(&real_data[i * sizeof(float)], &x, sizeof(x)); 
    } 

    dispatch(std::move(real_data)); 
} 
+0

당신이이 옵션을 제시해 주셔서 감사합니다. 'float * '을 필요로하고 전체 데이터 세트에서 작동하는 숫자 라이브러리를 사용합니다. –

+0

고마워요. 실제로 많은 경우에 매우 유용한 해결 방법입니다. 그러나 @BenVoigt가 언급했듯이 이상적으로 필요한 것은 "꽤"아닙니다. – Frank