2017-10-26 4 views
2

Das ist so ein einfaches Muster, es muss eine "nette" Art und Weise sein, es zu sortieren.Effizientes Erzeugen von Byte-Puffer ohne striktes Aliasing

Ich habe eine Funktion, die eine dynamisch große Byte-Array mit arithmetischen Daten generieren muss.

// 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)); 
} 

Leider scheint es sogar Klirren Heap elision Verwaltung ist nicht zu klären, was hier getan werden muss: see on godbolt

im schlimmsten Fall, ich dispatch() eine Vorlage machen, aber das würde sehr unordentlich, und ich bin neugierig zu sehen, ob es einen Ausweg aus dieser Unordnung gibt, die ich sowieso übersehe.

Danke!

Edit: A dachte nur, fiel mir ein (unmittelbar nach der Frage natürlich veröffentlichen ...): Ich real_data als Zuteilungs behandeln könnte und an Ort und Stelle neu die arithmetischen Daten oben drauf:

Dies sieht funky wie die Hölle, aber ich denke, es könnte legal sein. Könnte sein?

+0

Was wird 'dispatch' mit' data' tun? Wenn es auf es als "float" oder "char" zugreift, gibt es kein Problem, denke ich. – geza

+0

@geza Es ist egal, was der Versand mit den Daten macht, was 'bad_foo()' tut, ist ein Verstoß an sich. – Frank

+0

Ich bin nicht wirklich sicher, dass das der Fall ist. Sie greifen nur auf diesen Speicher als 'float' zu. Verstößt es wirklich gegen die strenge Aliasing-Regel? (Ich sage nicht, dass es nicht ist, ich bin nur skeptisch) – geza

Antwort

2

Der sicherste Weg, Aliasing-Regeln zu umgehen, ist die Verwendung von memcpy(), aber Sie müssen dies nicht für eine ganze zweite Kopie der Daten tun. Ich würde vorschlagen, alle Ihre float Arbeit an einer lokalen float Variable und dann memcpy() in die richtige Position in Ihrem real_data Puffer ein Element zu einer Zeit. Die meisten Compiler werden dies meiner Erfahrung nach effektiv optimieren.

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

Froh, dass Sie diese Option präsentiert, auch wenn es nicht helfen kann, wenn Sie sind Verwenden einer numerischen Bibliothek, die ein 'float *' benötigt, und arbeitet mit dem gesamten Datensatz. –

+0

Vielen Dank dafür, es ist in der Tat in vielen Fällen ein sehr nützlicher Workaround, aber wie @BenVoigt erwähnt, ist es nicht "ganz" was ich ideal brauchen würde. – Frank

Verwandte Themen