2017-06-12 15 views
0

私はopenclには少し新しく、boost :: computeを正しく使用する方法を学んでいます。boost :: computeクロージャーまたは関数への参照によってカスタム構造体のベクトルを渡します。

#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"; 
    } 
} 

私は(実際にははるかに複雑ここに示されているよりも)カスタム構造体のベクトルを持って、私はGPUに処理したい:次のコードを考えてみましょう。コメントアウトされていないBOOST_COMPUTE_CLOSUREでは、compute::transformは値によって構造体を渡し、それらを処理して元に戻します。

プログラムが実行されると、私はこれを達成する方法を言及するすべての文書を発見していないとき、私はcompute::for_eachでコメントアウトBOOST_COMPUTE_CLOSUREに示すように参照することによってこれらを渡したいと思いますが、カーネルがコンパイルする(Build Program Failureを)失敗しました。 を使って参照渡し(実際にはポインタはC99なので)、構造体のベクトル全体にポインタを渡すことで実現できますが、compute::...の関数をもっとエレガントに見せたいと思います。

答えて

1

BOOST_COMPUTE_DEBUG_KERNEL_COMPILATIONマクロを定義してOpenCLプログラムをビルドできない場合、プログラムソースとビルドログがstdoutに書き込まれます。

BOOST_COMPUTE_CLOSUREで実行しようとしているOpenCL Cでの参照渡しはできません。 __globalポインタをクロージャに渡して、その値のローカルコピーではなく、グローバルメモリ内の変数の値を変更したいと思います。私はそれがfor_each(と他のアルゴリズム)でBoost.Computeは常にあなたの関数/クロージャに値を渡すので、それがBoost.Computeでサポートされているとは思わない。

もちろん、回避策を実装することもできます。つまり、単精度の&演算子を追加するか、カスタムデバイスイテレータを実装します。ただし、提示された例では、パフォーマンスが低下します。これは、非集約メモリの読み書きにつながるためです。複雑な構造(AoS)が非常に多い場合は、配列の構造(SoA)を変更したり、構造を分割したりしてください。

関連する問題