2017-06-12 3 views
0

Je suis un peu nouveau à opencl et j'essaie d'apprendre à utiliser boost :: calculer correctement. Considérez le code suivant:Passez un vecteur de structures personnalisées en référence à un boost :: calcul de fermeture ou de la fonction

#include <iostream> 
#include <vector> 
#include <boost/compute.hpp> 

const cl_int cell_U_size{ 4 }; 

#pragma pack (push,1) 
struct Cell 
{ 
    cl_double U[cell_U_size]; 
}; 
#pragma pack (pop) 

BOOST_COMPUTE_ADAPT_STRUCT(Cell, Cell, (U)); 

int main(int argc, char* argv[]) 
{ 
    using namespace boost; 
    auto device = compute::system::default_device(); 
    auto context = compute::context(device); 
    auto queue = compute::command_queue(context, device); 

    std::vector<Cell> host_Cells; 
    host_Cells.reserve(10); 
    for (auto j = 0; j < host_Cells.capacity(); ++j) { 
     host_Cells.emplace_back(Cell()); 
     for (auto i = 0; i < cell_U_size; ++i) { 
      host_Cells.back().U[i] = static_cast<cl_double>(i+j); 
     } 
    } 
    std::cout << "Before:\n"; 
    for (auto const& hc : host_Cells) { 
     for (auto const& u : hc.U) 
      std::cout << " " << u; 
     std::cout << "\n"; 
    } 
    compute::vector<Cell> device_Cells(host_Cells.size(), context); 
    auto f = compute::copy_async(host_Cells.begin(), host_Cells.end(), device_Cells.begin(), queue); 
    try { 
     BOOST_COMPUTE_CLOSURE(Cell, Step1, (Cell cell), (cell_U_size), { 
      for (int i = 0; i < cell_U_size; ++i) { 
       cell.U[i] += 1.0; 
      } 
      return cell; 
     }); 
     f.wait(); // Wait for data to finish being copied 
     compute::transform(device_Cells.begin(), device_Cells.end(), device_Cells.begin(), Step1, queue); 

     //BOOST_COMPUTE_CLOSURE(void, Step2, (Cell &cell), (cell_U_size), { 
     // for (int i = 0; i < cell_U_size; ++i) { 
     //  cell.U[i] += 1.0; 
     // } 
     //}); 
     //compute::for_each(device_Cells.begin(), device_Cells.end(), Step2, queue); 

     compute::copy(device_Cells.begin(), device_Cells.end(), host_Cells.begin(), queue); 
    } 
    catch (std::exception &e) { 
     std::cout << e.what() << std::endl; 
     throw; 
    } 
    std::cout << "After:\n"; 
    for (auto const& hc : host_Cells) { 
     for (auto const& u : hc.U) 
      std::cout << " " << u; 
     std::cout << "\n"; 
    } 
} 

J'ai un vecteur de struct personnalisés (en réalité beaucoup plus complexe que montré ici) que je veux traiter sur le GPU. Dans le commentaire non BOOST_COMPUTE_CLOSURE le compute::transform passe les structures par valeur, les traite et les recopie ensuite.

Je voudrais les transmettre par référence comme indiqué dans l'en commentaire BOOST_COMPUTE_CLOSURE avec compute::for_each, mais le noyau ne parvient pas à compiler (Build Program Failure) lorsque le programme est exécuté et je l'ai trouvé aucune documentation mentionnant comment cela devrait être atteint.

Je sais que je peux réaliser en passant par référence (pointeurs en fait, car il est C99) en utilisant BOOST_COMPUTE_STRINGIZE_SOURCE et en passant un pointeur sur le vecteur entier de struct, mais je voudrais utiliser les compute::... fonctions que celles-ci semblent plus élégant.

Répondre

1

Si vous définissez la macro BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION et que le programme OpenCL de construction échoue, la source du programme et le journal de génération seront écrits sur stdout.

Vous ne pouvez pas passer par référence dans OpenCL C, que vous essayez de faire dans le BOOST_COMPUTE_CLOSURE. Je comprends que vous souhaitez passer un pointeur __global à votre fermeture et modifier les valeurs de la variable dans la mémoire globale, pas de la copie locale de cette valeur. Je ne pense pas qu'il soit pris en charge dans Boost.Compute, car dans for_each (et d'autres algorithmes) Boost.Compute passe toujours la valeur à votre fonction/fermeture.

Bien sûr, vous pouvez toujours implémenter une solution de contournement: ajoutez un opérateur & unaire ou implémentez un itérateur de périphérique personnalisé. Cependant, dans l'exemple présenté, cela réduirait simplement les performances, car cela conduirait à des lectures et écritures de mémoire non coalescées. Si vous avez un très grand nombre de structures complexes (AoS), essayez de changer la structure des tableaux (SoA) ou/et de casser votre structure.