Il ya quelque temps, j'ai écrit un après sur les normales de surface dans OpenGL ES. Hier sur Twitter, il ya eu quelques discussions sur l'utilisation de la fonction racine carré inverse de Quake 3 pour accélérer les performances des applications iPhone OpenGL ES. Voici ce que cette méthode ressemble (convertis en utilisant GL et iPhone types de données):
La racine carrée inverse peut être utilisé de plusieurs façons. Noel Llopis des Snappy tactile souligné deux utilisations pour elle sur Twitter hier: le calcul des normales et faisant sphériques mappage de texture UV. Je suis encore en train d'envelopper ma tête dans le Texture Mapping UV, mais je comprends assez bien les normales à ce stade, donc je si j'avais voir quel genre de gains de performance je pourrais obtenir en utilisant cette optimisation vieux. Il ya toutes sortes d'arguments autour de la intertubes savoir si cette fonction donne encore des gains de performance, mais il ya un moyen facile de le savoir: c'est l'utilisation et de mesurer avec Shark.
J'ai utilisé mon Chargeur Wavefront OBJ comme un test, et profilée du chargement de la plus complexe des trois objets - l'avion. La première manche a été avec mon code original, qui bêtement1 sqrt utilisés (). J'ai ensuite re-couru à l'aide sqrtf (), puis à nouveau en utilisant l'InvSqrt Quake3D () la fonction ci-dessus.
Les résultats sont impressionnants, et vous avez certainement do obtenir une augmentation des performances de l'utilisation de cette fonction vieux de dix ans sur l'iPhone. InvSqrt aide () a donné une diminution de 15% du temps passé à calculer les normales de surface sur l'aide sqrtf () et une diminution de 40% par rapport à calculer avec sqrt (). Ce n'est pas une somme à dédaigner, surtout dans les situations où vous avez besoin de calculer les normales sur le temps de voler de nombreux seconde.
Maintenant, si vous vous souvenez, c'était comment nous avons calculé les normales en utilisant la fonction racine carrée de math.h:
Alors ... comment peut-on modifier cette option pour utiliser la racine carrée inverse? Eh bien, la racine carrée inverse d'un nombre est simplement une divisé par la racine carrée de ce nombre. En Vector3DNormalize (), on divise chacune des composantes du vecteur (x, y et z) par la grandeur du vecteur, qui est calculée en utilisant la racine carrée. Depuis divisant une valeur par un nombre est le même que la multiplication par 1 divisé par ce même nombre, donc, nous pouvons simplement multiplier chaque composante par l'ampleur inverses au lieu, comme ceci:
Doux, non? Si nous utilisons maintenant Vector3DFastNormalize () au lieu de Vector3DNormalize (), et chaque appel sera d'environ 15% plus rapide sur les générations actuelles de l'iPhone et l'iPod Touch par rapport à l'utilisation du haut-fonction racine carrée.
Mais ... il ya un hic. En fait, deux prises.
La première prise est que cette optimisation ne fonctionne pas plus rapidement sur tout le matériel. En fait, sur certains matériels, il est mesurable lent que l'utilisation sqrtf (). Cela signifie que vous êtes de jeu que le matériel futures profiteront également de cette optimisation mêmes. Pas une affaire énorme et très probablement une valeur sûre, mais vous devriez en être conscient et être prêt à revenir rapidement qu'Apple devrait sortir un nouvelle génération d'iPhones et d'iPod Touch qui utilisent un processeur différent.
Le deuxième cran, et beaucoup plus important est les ramifications juridiques possibles de l'utilisation de ce code. Vous voyez, Id publié le code source Quake3D en vertu de la Licence publique générale GNU, qui est une licence virale. Si vous utilisez le code source à partir d'un projet GPL, vous devez ouvrir la source de votre projet dans son ensemble sous la licence GPL ainsi. Maintenant, c'est une simplification excessive, et il ya des façons de contourner la GPL, mais en règle générale, si vous utilisez du code sous GPL, vous devez rendre votre code GPL également.
Mais, les eaux sont un peu sombres. John Carmack a admis qu'il n'a pas écrit cette fonction, et ne pense pas que les autres programmeurs à Id ne soit. L'auteur réel de ce code est inconnu. Certains des contributeurs à la fonction ont été trouvés, mais pas l'auteur original. Cela signifie que le code pourrait être dans le domaine public. Si c'est le cas, son inclusion dans une application GPL ne pas sortir du domaine public.
Ainsi, la ligne du bas: est-il sûr? Probablement. Cette fonction est largement connu et largement utilisé et il n'y a eu aucune indication que tout propriétaire possible des droits a tout intérêt à poursuivre de toute utilisation de cette fonction. Y at-il des garanties? Nope.
Ma recommandation est de l'utiliser, mais assurez-vous que chaque endroit que vous l'utilisez, ont une méthode de sauvegarde que vous pouvez repli sur si vous avez besoin. Si vous voulez une certaine assurance, vous pourriez essayer de contacter Id juridiques et d'obtenir une dispense d'utiliser cette fonction. Je ne sais pas si ils vont répondre, ou si ils vont lui accorder, mais les gens de chez Id m'ont toujours frappé comme de bonnes personnes, de sorte qu'il pourrait être utile à une enquête si vous êtes une aversion au risque.
1 - sqrt () est une fonction en double précision. Depuis OpenGL ES ne supporte pas le type de données GLDouble, ce qui signifie que je faisais le calcul sur les bits deux fois plus nombreux que nécessaire, et en convertissant en arrière du simple au double précision, puis revenir.
static inline GLfloat InvSqrt(GLfloat x)
{
GLfloat xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(GLfloat*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}La racine carrée inverse peut être utilisé de plusieurs façons. Noel Llopis des Snappy tactile souligné deux utilisations pour elle sur Twitter hier: le calcul des normales et faisant sphériques mappage de texture UV. Je suis encore en train d'envelopper ma tête dans le Texture Mapping UV, mais je comprends assez bien les normales à ce stade, donc je si j'avais voir quel genre de gains de performance je pourrais obtenir en utilisant cette optimisation vieux. Il ya toutes sortes d'arguments autour de la intertubes savoir si cette fonction donne encore des gains de performance, mais il ya un moyen facile de le savoir: c'est l'utilisation et de mesurer avec Shark.
J'ai utilisé mon Chargeur Wavefront OBJ comme un test, et profilée du chargement de la plus complexe des trois objets - l'avion. La première manche a été avec mon code original, qui bêtement1 sqrt utilisés (). J'ai ensuite re-couru à l'aide sqrtf (), puis à nouveau en utilisant l'InvSqrt Quake3D () la fonction ci-dessus.
Les résultats sont impressionnants, et vous avez certainement do obtenir une augmentation des performances de l'utilisation de cette fonction vieux de dix ans sur l'iPhone. InvSqrt aide () a donné une diminution de 15% du temps passé à calculer les normales de surface sur l'aide sqrtf () et une diminution de 40% par rapport à calculer avec sqrt (). Ce n'est pas une somme à dédaigner, surtout dans les situations où vous avez besoin de calculer les normales sur le temps de voler de nombreux seconde.
Maintenant, si vous vous souvenez, c'était comment nous avons calculé les normales en utilisant la fonction racine carrée de math.h:
static inline GLfloat Vector3DMagnitude(Vector3D vector)
{
return sqrt((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
static inline void Vector3DNormalize(Vector3D *vector)
{
GLfloat vecMag = Vector3DMagnitude(*vector);
if ( vecMag == 0.0 )
{
vector->x = 1.0;
vector->y = 0.0;
vector->z = 0.0;
}
vector->x /= vecMag;
vector->y /= vecMag;
vector->z /= vecMag;
}Alors ... comment peut-on modifier cette option pour utiliser la racine carrée inverse? Eh bien, la racine carrée inverse d'un nombre est simplement une divisé par la racine carrée de ce nombre. En Vector3DNormalize (), on divise chacune des composantes du vecteur (x, y et z) par la grandeur du vecteur, qui est calculée en utilisant la racine carrée. Depuis divisant une valeur par un nombre est le même que la multiplication par 1 divisé par ce même nombre, donc, nous pouvons simplement multiplier chaque composante par l'ampleur inverses au lieu, comme ceci:
static inline GLfloat Vector3DFastInverseMagnitude(Vector3D vector)
{
return InvSqrt((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
static inline void Vector3DFastNormalize(Vector3D *vector)
{
GLfloat vecInverseMag = Vector3DFastInverseMagnitude(*vector);
if (vecInverseMag == 0.0)
{
vector->x = 1.0;
vector->y = 0.0;
vector->z = 0.0;
}
vector->x *= vecInverseMag;
vector->y *= vecInverseMag;
vector->z *= vecInverseMag;
}
Doux, non? Si nous utilisons maintenant Vector3DFastNormalize () au lieu de Vector3DNormalize (), et chaque appel sera d'environ 15% plus rapide sur les générations actuelles de l'iPhone et l'iPod Touch par rapport à l'utilisation du haut-fonction racine carrée.
Mais ... il ya un hic. En fait, deux prises.
Les captures
La première prise est que cette optimisation ne fonctionne pas plus rapidement sur tout le matériel. En fait, sur certains matériels, il est mesurable lent que l'utilisation sqrtf (). Cela signifie que vous êtes de jeu que le matériel futures profiteront également de cette optimisation mêmes. Pas une affaire énorme et très probablement une valeur sûre, mais vous devriez en être conscient et être prêt à revenir rapidement qu'Apple devrait sortir un nouvelle génération d'iPhones et d'iPod Touch qui utilisent un processeur différent.
Le deuxième cran, et beaucoup plus important est les ramifications juridiques possibles de l'utilisation de ce code. Vous voyez, Id publié le code source Quake3D en vertu de la Licence publique générale GNU, qui est une licence virale. Si vous utilisez le code source à partir d'un projet GPL, vous devez ouvrir la source de votre projet dans son ensemble sous la licence GPL ainsi. Maintenant, c'est une simplification excessive, et il ya des façons de contourner la GPL, mais en règle générale, si vous utilisez du code sous GPL, vous devez rendre votre code GPL également.
Mais, les eaux sont un peu sombres. John Carmack a admis qu'il n'a pas écrit cette fonction, et ne pense pas que les autres programmeurs à Id ne soit. L'auteur réel de ce code est inconnu. Certains des contributeurs à la fonction ont été trouvés, mais pas l'auteur original. Cela signifie que le code pourrait être dans le domaine public. Si c'est le cas, son inclusion dans une application GPL ne pas sortir du domaine public.
Ainsi, la ligne du bas: est-il sûr? Probablement. Cette fonction est largement connu et largement utilisé et il n'y a eu aucune indication que tout propriétaire possible des droits a tout intérêt à poursuivre de toute utilisation de cette fonction. Y at-il des garanties? Nope.
Ma recommandation est de l'utiliser, mais assurez-vous que chaque endroit que vous l'utilisez, ont une méthode de sauvegarde que vous pouvez repli sur si vous avez besoin. Si vous voulez une certaine assurance, vous pourriez essayer de contacter Id juridiques et d'obtenir une dispense d'utiliser cette fonction. Je ne sais pas si ils vont répondre, ou si ils vont lui accorder, mais les gens de chez Id m'ont toujours frappé comme de bonnes personnes, de sorte qu'il pourrait être utile à une enquête si vous êtes une aversion au risque.
1 - sqrt () est une fonction en double précision. Depuis OpenGL ES ne supporte pas le type de données GLDouble, ce qui signifie que je faisais le calcul sur les bits deux fois plus nombreux que nécessaire, et en convertissant en arrière du simple au double précision, puis revenir.
Aucun commentaire:
Enregistrer un commentaire