Я пишу небольшой трассировщик лучей, использующий иерархии ограничивающих объемов для ускорения трассировки лучей.
Короче говоря, у меня есть двоичное дерево, и мне может понадобиться посетить несколько листов.
Текущий У меня есть узел с двумя дочерними элементами слева и справа, затем во время travel (), если какое-то условие, в этом примере intersect (), посещают дочерние элементы:
class BoundingBoxNode{
BoundingBoxNode* left, *right;
void travel(param &p);
inline bool intersect(param &p){...};
};
void BoundingBoxNode::travel(param &p){
if(this->intersect(p)){
if(left)
left->travel(p);
if(right)
right->travel(p);
}
}
В этом подходе используются рекурсивные вызовы методов, однако мне нужно максимально оптимизировать этот код ... А согласно справочному руководству по оптимизации для IA-32 вызовы функций глубже 16 могут быть очень дорогими, поэтому я бы хотел сделать это, используя цикл while вместо рекурсивных вызовов.
Но я НЕ хочу делать динамическое выделение кучи, поскольку это дорого. Поэтому я подумал, что, возможно, я мог бы использовать тот факт, что каждый раз, когда цикл while начинается над стеком, будет в одной и той же позиции.
В следующем очень уродливом хаке я полагаюсь на alloca (), чтобы всегда выделять один и тот же адрес:
class BoundingBoxNode{
BoundingBoxNode* left, right;
inline void travel(param &p){
int stack_size = 0;
BoundingBoxNode* current = this;
while(stack_size >= 0){
BoundingBoxNode* stack = alloca(stack_size * 4 + 2*4);
if(current->intersect(p)){
if(current->left){
stack[stack_size] = current->left;
stack_size++;
}
if(current->right){
stack[stack_size] = current->right;
stack_size++;
}
}
stack_size--;
current = stack[stack_size];
}
};
inline bool intersect(param &p){...};
};
Как ни удивительно, но такой подход может не сработать :)
Но он работает до тех пор, пока размер стека меньше 4 или 5 ... Я также вполне уверен, что такой подход возможен, просто я действительно нуждаюсь в некоторой помощи для его правильной реализации.
Итак, как я могу манипулировать стеком вручную из C ++, возможно ли, что я могу использовать какое-то расширение компилятора ... Или я должен сделать это на ассемблере, и если да, то как мне написать ассемблер, который может быть скомпилирован с обоими GCC и ICC.
Надеюсь, кто-нибудь сможет мне помочь ... Мне не нужно идеальное решение, просто взлом, если оно работает, этого достаточно для этого:)
С уважением, Джонас Финнеманн Дженсен