2017-06-03 2 views
3

J'ai une question concernant l'utilisation des structures dans OpenCL sur un processeur Intel. Mon noyau en cours d'accéder à deux tampons en utilisant une struct de la manière suivante:Compilateur Intel OpenCL: optimisation de l'utilisation de la structure

struct pair { 
    float first; 
    float second; 
}; 

inline const float f(const struct pair param) { 
    return param.first * param.second; 
} 

inline const struct pair access_func(__global float const * const a, __global float const * const b, const int i) { 
    struct pair res = { 
      a[i], 
      b[i] 
    }; 
    return res; 
} 

// slow 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = f(access_func(a, b, i)); 

// ... 
} 

Lorsque je modifie le noyau de la manière suivante, il tourne beaucoup plus vite:

// fast 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = a[i] * b[ i ]; 

// ... 
} 

Est-il possible de laisser le processeur Intel compilateur faire cette optimisation? Le compilateur NVIDIA semble être capable de le faire, car je ne vois pas de différence dans l'exécution sur un GPU.

Merci d'avance!

+0

Pourrait-il être tout ce qui est const et mettre un stress élevé sur la gestion du cache? –

+0

J'ai essayé de supprimer les mots clés 'const', mais cela n'a pas résolu le problème. –

Répondre

0

Le compilateur ne peut pas effectuer d'optimisations sur la mise en mémoire de vos données, étant donné que les tampons sont partagés entre le périphérique OpenCL et l'hôte, et/ou entre plusieurs noyaux sur le périphérique OpenCL; la disposition la plus efficace dépendra des modèles d'accès dans le noyau, et ceux-ci peuvent évidemment être différents pour chaque noyau.

Vous devrez choisir judicieusement la disposition de la mémoire de vos données; C'est l'une des parties les plus difficiles de la programmation GPU. Reportez-vous aux guides d'optimisation OpenCL pour chaque implémentation que vous ciblez pour savoir ce qu'ils préfèrent. Parfois, des modèles d'accès inefficaces peuvent être masqués en copiant de la mémoire global vers la mémoire local, puis en travaillant à partir de la copie locale.

+1

J'ai essayé d'ajouter le mot clé 'restrict' pour signaler au compilateur que les tampons ne sont pas partagés, mais le problème persiste. Je comprends que la disposition de la mémoire est importante, mais est-ce vraiment le problème ici? Comme je l'ai mentionné dans ma question, le problème ne se produit que sur un processeur. Apparemment, l'optimisation peut être faite sur un GPU. –

+0

x86 Les UC ont besoin de plus d'instructions pour faire de l'arithmétique «horizontale» et emballer les résultats de manière appropriée pour un traitement ultérieur via SIMD (SSE/AVX), qui est généralement compilé par le compilateur OpenCL. Les GPU sont généralement structurés fondamentalement différemment, et sont conçus pour gérer ce type de situation, car il est courant d'avoir des buffers de vertex de type tableau-de-struct. Donc, le compilateur ne réorganise pas les données, le GPU le gère plus efficacement. Les processeurs fonctionnent mieux avec la structure des structures. (Voir: SOA vs AOS) – pmdj

+0

Je viens de vérifier, et je ne trouve pas d'instructions de multiplication horizontale dans SSE ou AVX, donc ce sera pourquoi. Le compilateur génère probablement au moins autant d'instructions de "décompression" que de multiplications. La disposition des données est importante! – pmdj