Je n'ai pas regardé dans les compilateurs actuels, mais en règle général, la vectorisation n'est pas possible dans les boucles non-pures, c'est à dire contenant un break ou un return conditionnel. Je ne dis pas que c'est toujours impossible mais c'est rarement intéressant donc les compilateurs n'essayent même pas.
Je tiens aussi à signaler que strictement parlant, la vectorisation SSE proposée ici est illégale. Le problème est que les données sont lues par blocs de 4 int (donc 16 octets). En pratique, cela signifie que la boucle vectorisée peut lire 1, 2 ou 3 int supplémentaire. Cela pourrait causer un dépassement de tableau et donc un 'segfault'. Un bon compilateur ne fera pas cela.
Remarque: Le fait que les indices lus soient tous inférieurs à n n'a pas d'importance car, du point de vue du compilateur, l'argument n n'indique pas la taille du taille du tableau. Par exemple, si l'utilisateur est certain que son tableau contient au moins une fois la valeur, il pourrait décider d'utiliser n=INT_MAX.
J'imagine qu'ICC fait quelques tests supplémentaires sur les alignements des pointeurs dans son implémentation de std::find(). Cela entraîne évidemment un petit surcoût qui peut ne pas être négligeable quand n est petit. C'est une information que le compilateur ne possède généralement pas (sauf inlining ou analyse inter-procedurale).
Il ne faut pas non plus oublier que pour respecter les conventions d'appels, les codes vectorisés doivent aussi sauver et restaurer plus de registres (push/pop dans la pile). C'est un autre surcoût qu'il faut prendre en compte pour décider si la vectorisation est intéressante.
PS: Dans ton benchmark, toutes les fonctions sont dans le même fichier. Il n'est pas impossible qu'ICC réussisse à optimiser std::find en inlinant systématiquement tout les appels de fonctions (donc potentiellement plus d'info sur n et sur l'alignement des données). Obtiens tu les même perfs quand find_int_cpp() est compilé dans un fichier séparé?
# Vectorisation illégale
Posté par SChauveau . En réponse au journal Recherche de valeur dans un tableau et l'écosystème des compilateurs C++. Évalué à 8.
Je n'ai pas regardé dans les compilateurs actuels, mais en règle général, la vectorisation n'est pas possible dans les boucles non-pures, c'est à dire contenant un
breakou unreturnconditionnel. Je ne dis pas que c'est toujours impossible mais c'est rarement intéressant donc les compilateurs n'essayent même pas.Je tiens aussi à signaler que strictement parlant, la vectorisation SSE proposée ici est illégale. Le problème est que les données sont lues par blocs de 4
int(donc 16 octets). En pratique, cela signifie que la boucle vectorisée peut lire 1, 2 ou 3intsupplémentaire. Cela pourrait causer un dépassement de tableau et donc un 'segfault'. Un bon compilateur ne fera pas cela.Remarque: Le fait que les indices lus soient tous inférieurs à
nn'a pas d'importance car, du point de vue du compilateur, l'argumentnn'indique pas la taille du taille du tableau. Par exemple, si l'utilisateur est certain que son tableau contient au moins une fois la valeur, il pourrait décider d'utiliser n=INT_MAX.J'imagine qu'ICC fait quelques tests supplémentaires sur les alignements des pointeurs dans son implémentation de std::find(). Cela entraîne évidemment un petit surcoût qui peut ne pas être négligeable quand
nest petit. C'est une information que le compilateur ne possède généralement pas (sauf inlining ou analyse inter-procedurale).Il ne faut pas non plus oublier que pour respecter les conventions d'appels, les codes vectorisés doivent aussi sauver et restaurer plus de registres (push/pop dans la pile). C'est un autre surcoût qu'il faut prendre en compte pour décider si la vectorisation est intéressante.
PS: Dans ton benchmark, toutes les fonctions sont dans le même fichier. Il n'est pas impossible qu'ICC réussisse à optimiser
std::finden inlinant systématiquement tout les appels de fonctions (donc potentiellement plus d'info surnet sur l'alignement des données). Obtiens tu les même perfs quandfind_int_cpp()est compilé dans un fichier séparé?