質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

受付中

高位合成に用いたベンチマークのC++での実行

leniladge.dck
leniladge.dck

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

2回答

0評価

0クリップ

464閲覧

投稿2022/01/31 14:54

Vitisというソフトを用いてハードウェアアクセラレーションを行ったのですが,その比較として高位合成前のC++のコードを実行しようとしました.
用いたコードは以下のものです

krnl_vadd.cpp

#define BUFFER_SIZE 256 #define DATA_SIZE 4194304 #define m_axi_port 128 //変更点はここだけ //TRIPCOUNT identifier const unsigned int c_len = DATA_SIZE / BUFFER_SIZE; const unsigned int c_size = BUFFER_SIZE; /* Vector Addition Kernel Implementation Arguments: in1 (input) --> Input Vector1 in2 (input) --> Input Vector2 out_r (output) --> Output Vector size (input) --> Size of Vector in Integer */ extern "C" { void krnl_vadd(const unsigned int *in1, // Read-Only Vector 1 const unsigned int *in2, // Read-Only Vector 2 unsigned int *out_r, // Output Result int size // Size in integer ) { #pragma HLS INTERFACE m_axi port = in1 offset = slave bundle = gmem #pragma HLS INTERFACE m_axi port = in2 offset = slave bundle = gmem #pragma HLS INTERFACE m_axi port = out_r offset = slave bundle = gmem #pragma HLS INTERFACE s_axilite port = in1 bundle = control #pragma HLS INTERFACE s_axilite port = in2 bundle = control #pragma HLS INTERFACE s_axilite port = out_r bundle = control #pragma HLS INTERFACE s_axilite port = size bundle = control #pragma HLS INTERFACE s_axilite port = return bundle = control unsigned int v1_buffer[BUFFER_SIZE]; // Local memory to store vector1 //Per iteration of this loop perform BUFFER_SIZE vector addition for (int i = 0; i < size; i += BUFFER_SIZE) { #pragma HLS LOOP_TRIPCOUNT min=c_len max=c_len int chunk_size = BUFFER_SIZE; //boundary checks if ((i + BUFFER_SIZE) > size) chunk_size = size - i; read1: for (int j = 0; j < chunk_size; j++) { #pragma HLS LOOP_TRIPCOUNT min=c_size max=c_size #pragma HLS PIPELINE II=1 v1_buffer[j] = in1[i + j]; } //Burst reading B and calculating C and Burst writing // to Global memory vadd_writeC: for (int j = 0; j < chunk_size; j++) { #pragma HLS LOOP_TRIPCOUNT min=c_size max=c_size #pragma HLS PIPELINE II=1 //perform vector addition out_r[i+j] = v1_buffer[j] + in2[i+j]; } } } }

vadd.cpp

#include <stdlib.h> #include <fstream> #include <iostream> #include "vadd.h" static const int DATA_SIZE = 4194304; static const std::string error_message = "Error: Result mismatch:\n" "i = %d CPU result = %d Device result = %d\n"; int main(int argc, char* argv[]) { //TARGET_DEVICE macro needs to be passed from gcc command line if(argc != 2) { std::cout << "Usage: " << argv[0] <<" <xclbin>" << std::endl; return EXIT_FAILURE; } char* xclbinFilename = argv[1]; // Compute the size of array in bytes size_t size_in_bytes = DATA_SIZE * sizeof(int); // Creates a vector of DATA_SIZE elements with an initial value of 10 and 32 // using customized allocator for getting buffer alignment to 4k boundary std::vector<cl::Device> devices; cl::Device device; std::vector<cl::Platform> platforms; bool found_device = false; //traversing all Platforms To find Xilinx Platform and targeted //Device in Xilinx Platform cl::Platform::get(&platforms); for(size_t i = 0; (i < platforms.size() ) & (found_device == false) ;i++){ cl::Platform platform = platforms[i]; std::string platformName = platform.getInfo<CL_PLATFORM_NAME>(); if ( platformName == "Xilinx"){ devices.clear(); platform.getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices); if (devices.size()){ device = devices[0]; found_device = true; break; } } } if (found_device == false){ std::cout << "Error: Unable to find Target Device " << device.getInfo<CL_DEVICE_NAME>() << std::endl; return EXIT_FAILURE; } // Creating Context and Command Queue for selected device cl::Context context(device); cl::CommandQueue q(context, device, CL_QUEUE_PROFILING_ENABLE); // Load xclbin std::cout << "Loading: '" << xclbinFilename << "'\n"; std::ifstream bin_file(xclbinFilename, std::ifstream::binary); bin_file.seekg (0, bin_file.end); unsigned nb = bin_file.tellg(); bin_file.seekg (0, bin_file.beg); char *buf = new char [nb]; bin_file.read(buf, nb); // Creating Program from Binary File cl::Program::Binaries bins; bins.push_back({buf,nb}); devices.resize(1); cl::Program program(context, devices, bins); // This call will get the kernel object from program. A kernel is an // OpenCL function that is executed on the FPGA. cl::Kernel krnl_vector_add(program,"krnl_vadd"); // These commands will allocate memory on the Device. The cl::Buffer objects can // be used to reference the memory locations on the device. cl::Buffer buffer_a(context, CL_MEM_READ_ONLY, size_in_bytes); cl::Buffer buffer_b(context, CL_MEM_READ_ONLY, size_in_bytes); cl::Buffer buffer_result(context, CL_MEM_WRITE_ONLY, size_in_bytes); //set the kernel Arguments int narg=0; krnl_vector_add.setArg(narg++,buffer_a); krnl_vector_add.setArg(narg++,buffer_b); krnl_vector_add.setArg(narg++,buffer_result); krnl_vector_add.setArg(narg++,DATA_SIZE); //We then need to map our OpenCL buffers to get the pointers int *ptr_a = (int *) q.enqueueMapBuffer (buffer_a , CL_TRUE , CL_MAP_WRITE , 0, size_in_bytes); int *ptr_b = (int *) q.enqueueMapBuffer (buffer_b , CL_TRUE , CL_MAP_WRITE , 0, size_in_bytes); int *ptr_result = (int *) q.enqueueMapBuffer (buffer_result , CL_TRUE , CL_MAP_READ , 0, size_in_bytes); //setting input data for(int i = 0 ; i< DATA_SIZE; i++){ ptr_a[i] = 10; ptr_b[i] = 20; } // Data will be migrated to kernel space q.enqueueMigrateMemObjects({buffer_a,buffer_b},0/* 0 means from host*/); //Launch the Kernel q.enqueueTask(krnl_vector_add); // The result of the previous kernel execution will need to be retrieved in // order to view the results. This call will transfer the data from FPGA to // source_results vector q.enqueueMigrateMemObjects({buffer_result},CL_MIGRATE_MEM_OBJECT_HOST); q.finish(); //Verify the result int match = 0; for (int i = 0; i < DATA_SIZE; i++) { int host_result = ptr_a[i] + ptr_b[i]; if (ptr_result[i] != host_result) { printf(error_message.c_str(), i, host_result, ptr_result[i]); match = 1; break; } } q.enqueueUnmapMemObject(buffer_a , ptr_a); q.enqueueUnmapMemObject(buffer_b , ptr_b); q.enqueueUnmapMemObject(buffer_result , ptr_result); q.finish(); std::cout << "TEST " << (match ? "FAILED" : "PASSED") << std::endl; return (match ? EXIT_FAILURE : EXIT_SUCCESS); }

vadd.h

#pragma once #define CL_HPP_CL_1_2_DEFAULT_BUILD #define CL_HPP_TARGET_OPENCL_VERSION 120 #define CL_HPP_MINIMUM_OPENCL_VERSION 120 #define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY 1 #include <CL/cl2.hpp> //Customized buffer allocation for 4K boundary alignment template <typename T> struct aligned_allocator { using value_type = T; T* allocate(std::size_t num) { void* ptr = nullptr; if (posix_memalign(&ptr,4096,num*sizeof(T))) throw std::bad_alloc(); return reinterpret_cast<T*>(ptr); } void deallocate(T* p, std::size_t num) { free(p); } };

しかし,そのまま実行した場合は

PS C:\cpp\vadd_src> g++ krnl_vadd.cpp vadd.cpp -o vadd In file included from vadd.cpp:47: vadd.h:53:10: fatal error: CL/cl2.hpp: No such file or directory #include <CL/cl2.hpp> ^~~~~~~~~~~~ compilation terminated.

というエラーが発生(CL/cl2.hppがない)してしまいます.

CL/cl2.hppを用いずにこのプログラムを動かす方法はありますでしょうか.

また,実行にかかった時間なども知りたいのでその方法も教えていただけると助かります.

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

ozwk

2022/02/01 07:28

Vitis HLS側のCシミュレーションではだめですか?

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。