FC2カウンター FPGAの部屋 2015年06月29日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ラプラシアンフィルタのソフトウェアとハードウェアの速度の比較

ラプラシアンフィルタのVivado HLS 2014.4 でのCソースコードの最適化、ディレクティブの追加による速度の違いについては”Vivado HLS 2014.4 で合成したラプラシアンフィルタIPの高速化14(性能が最大になる設定を探る7、まとめ)”でまとめてある。これはZYBOを使用している

ZYBOのソフトウェアで実装したラプラシアンフィルタの実行速度は”ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける”で紹介したが、455 ms 程度だった。
しかし、これはソフトウェアの実装したCソースコードを使用している。Vivado HLS 2014.4 で使用したCソースコードは異なるものだ。
そこで、なるべくVivado HLSで使用したCソースコードを使用したらソフトウェアでは、どのくらい速くなるのかやってみた。
なお、”RTLを語る会(9) ~サヨナラHDL、Alteraよさらば!~”でご指摘を受けて、なるほど、そうだな。。。ということでやって見ることにした。ソフトウェアも高位合成のCソースコードに進化に合わせて比較してみる必要があるはず。。。
hanetsuki_y さん、ご指摘ありがとうございました。

なお、初期設定時間の違いを除いたラプラシアンフィルタの処理のみの経過時間を比較する。

ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける”の計測時間は初期設定時間も入っているので、初期設定時間を除いたラプラシアンフィルタ処理のみの時間を測定した。下に示す。
laplacian_filter がソフトウェア全体の処理時間、laplacian_filter1 が初期設定時間を除いたラプラシアンフィルタ処理のみの時間だ。
laplacian_filter1 はlaplacian_filter よりもわずかに短い。laplacian_filter は449 ms 程度、laplacian_filter1 は448 ms程度だ。
(2015/07/03: 値を修正)
soft_hard_comp_1_150629.png

最初に”Vivado HLS 2014.4 で合成したラプラシアンフィルタIPの高速化14(性能が最大になる設定を探る7、まとめ)”の”1.ディレクティブを与えていない状態でのラプラシアンフィルタの処理時間を示す。この時には、FCLK_CLK0からすべてのIP にクロックが供給されている。”の高位合成用のCソースコードをソフトウェア用Cソースコードに組み込んだ。下にその全ソースコードを示す。
2015/07/12:修正 時間計測にバグがあったので、修正しました。miyox さん、ありがとうございました)

// laplacian_filter2.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更
// Vivado HLS 2014.4 のプロジェクト http://marsee101.blog19.fc2.com/blog-entry-3102.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

#define CMA_START_ADDRESS           0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS    0x18200000  // 800*600*4 = 0x1d4c00

int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);

int main()
{
    volatile unsigned int *cam_fb = 0;
    volatile unsigned int *lap_fb = 0;
    volatile unsigned int *cam_addr;
    volatile unsigned int *lap_addr;
    int lap_fil_val;
    int x, y;
    struct timeval start_time, temp1, temp2, end_time;
    unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
    int a, b;
    int fl, sl, tl;
    int fd0, fd3;
      unsigned int offset_cam_addr, offset_lap_addr;
    unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
    volatile unsigned int *cam_fb_addr, *lap_fb_addr;
    int line_sel;
    volatile unsigned int *bmdc_axi_lites;
    volatile unsigned int *frame_buffer;

    // gettimeofday(&start_time, NULL);    // プログラム起動時の時刻を記録

    // frame_buffer にマップする
    fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 open error\n");
        exit(-1);
    }
    frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!frame_buffer){
        fprintf(stderr, "frame_buffer mmap error\n");
        exit(-1);
    }
    cam_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));

    // ラプラシアンフィルタの結果を入れておくフレーム・バッファ
    lap_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));

    offset_cam_addr = (volatile unsigned int)((unsigned int)cam_addr/sizeof(int));
    offset_lap_addr = (volatile unsigned int)((unsigned int)lap_addr/sizeof(int));
    
    gettimeofday(&start_time, NULL);
    
    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
   for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        fl = (y-1)%3;    // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
        sl = y%3;        // 2番めのライン
        tl = (y+1)%3;    // 3番目のライン
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
                lap_fil_val = 0;
            }else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
                lap_fil_val = 0;
            }else{
                 if (x == 1){ // ラインの最初でラインの画素を読み出す
                    if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
                        for (a=0; a<3; a++){ // 3ライン分
                            cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
                            memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                            for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
                                line_buf[a][b] = conv_rgb2y(line_buf[a][b]);    // カラーから白黒へ
                            }
                        }
                    } else { // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
                        cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
                         memcpy(line_buf[(y+1)%3], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                        for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
                            line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]);    // カラーから白黒へ
                        }
                    }
                }
                lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
            }
            lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
        }
        lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
        memcpy((void *)lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
    }
    
    gettimeofday(&end_time, NULL);
    
    munmap((void *)frame_buffer, 0x1000000);
 
   // ラプラシアンフィルタ表示画面に切り替え
    // Bitmap Display Controller AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 open error\n");
        exit(-1);
    }
    bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!bmdc_axi_lites){
        fprintf(stderr, "bmdc_axi_lites mmap error\n");
        exit(-1);
    }
    bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
    munmap((void *)bmdc_axi_lites, 0x10000);
    
    //gettimeofday(&end_time, NULL);
    if (end_time.tv_usec < start_time.tv_usec) {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 11000000 + end_time.tv_usec - start_time.tv_usec);
    }
    else {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
    }
    return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    return(y);
}

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
    int y;

    y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
    if (y<0)
        y = 0;
    else if (y>255)
        y = 255;
    return(y);
}

// 文字列が16進数かを調べる
int chkhex(char *str){
    while (*str != '\0'){
        if (!isxdigit(*str))
            return 0;
        str++;
    }
    return 1;
}


./laplacian_filter2 を実行した時に実行時間は 313 ms だった。Vivado HLS 2014.4 を使用してハードウェア化した時のラプラシアンフィルタ処理のみの時間は、80 ms だった。
よって、ハードウェア化シタ場合のラプラシアンフィルタの実行速度は、ソフトウェアで実行した場合の 313 ms / 80.0 ms ≒ 3.91 倍になったことがわかった。
soft_hard_comp_2_150629.png

次に、2.ラプラシアンフィルタのCソース中の割り算をカウンタで置き換えて、2箇所にPIPELINEディレクティブを追加した状態でのラプラシアンフィルタの処理時間を示す。この時にも、FCLK_CLK0からすべてのIP にクロックが供給されている。”場合との比較をしてみよう。ソフトウェアでは、単にラプラシアンフィルタのCソース中の割り算をカウンタで置き換えただけになる。これを laplacian_fitelr3.c とした。
これをgcc でコンパイルして、実行し、ラプラシアンフィルタ処理のみの時間を測定した。上の図の ./laplacian_filter3 を実行した時の時間がそれになる。その実行時間は、279 ms となり、laplacian_filter2 よりも 34 ms 高速になった。
Vivado HLS 2014.4 を使用してハードウェア化した時のラプラシアンフィルタ処理のみの時間は、60 ms だった。但し、PIPELINEディレクティブを追加してある。
よって、ハードウェア化した場合のラプラシアンフィルタの実行速度は、ソフトウェアで実行した場合の 279 ms / 60.0 ms = 4.65 倍になった。

laplacian_filter3.c を下に示す。
2015/07/12:修正 時間計測にバグがあったので、修正しました。miyox さん、ありがとうございました)

// laplacian_filter3.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更
// Vivado HLS 2014.4 のプロジェクト ZYBO/lap_filter_axim_2014_4を使用したソースコードと同じものを使用する

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

#define CMA_START_ADDRESS           0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS    0x18200000  // 800*600*4 = 0x1d4c00

int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);

int main()
{
    volatile unsigned int *cam_fb = 0;
    volatile unsigned int *lap_fb = 0;
    volatile unsigned int *cam_addr;
    volatile unsigned int *lap_addr;
    int lap_fil_val;
    int x, y;
    struct timeval start_time, temp1, temp2, end_time;
    unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
    int a, b;
    int fl, sl, tl;
    int fd0, fd3;
      unsigned int offset_cam_addr, offset_lap_addr;
    unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
    volatile unsigned int *cam_fb_addr, *lap_fb_addr;
    int line_sel;
    volatile unsigned int *bmdc_axi_lites;
    volatile unsigned int *frame_buffer;

    // gettimeofday(&start_time, NULL);    // プログラム起動時の時刻を記録

    // frame_buffer にマップする
    fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 open error\n");
        exit(-1);
    }
    frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!frame_buffer){
        fprintf(stderr, "frame_buffer mmap error\n");
        exit(-1);
    }
    cam_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));

    // ラプラシアンフィルタの結果を入れておくフレーム・バッファ
    lap_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));

    offset_cam_addr = (volatile unsigned int)((unsigned int)cam_addr/sizeof(int));
    offset_lap_addr = (volatile unsigned int)((unsigned int)lap_addr/sizeof(int));
    
    gettimeofday(&start_time, NULL);
    
    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
    for (y=0, line_sel=0; y<VERTICAL_PIXEL_WIDTH; y++){
        // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
        switch(line_sel){
            case 1 :
                fl = 0; sl = 1; tl = 2;
                break;
            case 2 :
                fl = 1; sl = 2; tl = 0;
                break;
            case 3 :
                fl = 2; sl = 0; tl = 1;
                break;
            default :
                fl = 0; sl = 1; tl = 2;
        }

        //fl = (y-1)%3;    // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
        //sl = y%3;        // 2番めのライン
        //tl = (y+1)%3;    // 3番目のライン
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
                lap_fil_val = 0;
            }else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
                lap_fil_val = 0;
            }else{
                 if (x == 1){ // ラインの最初でラインの画素を読み出す
                    if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
                        for (a=0; a<3; a++){ // 3ライン分
                            cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
                            memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                            for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){
#pragma HLS PIPELINE
 // ライン
                                line_buf[a][b] = conv_rgb2y(line_buf[a][b]);    // カラーから白黒へ
                            }
                        }
                    } else { // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
                        cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
                         memcpy(line_buf[tl], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                        for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){
#pragma HLS PIPELINE
 // ライン
                            line_buf[tl][b] = conv_rgb2y(line_buf[tl][b]);    // カラーから白黒へ
                        }
                    }
                }
                lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
            }
            lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
        }
        lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
        memcpy((void *)lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));

        line_sel++;
        if (line_sel > 3){
            line_sel = 1;
        }
    }
    
    gettimeofday(&end_time, NULL);
    
    munmap((void *)frame_buffer, 0x1000000);
 
   // ラプラシアンフィルタ表示画面に切り替え
    // Bitmap Display Controller AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 open error\n");
        exit(-1);
    }
    bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!bmdc_axi_lites){
        fprintf(stderr, "bmdc_axi_lites mmap error\n");
        exit(-1);
    }
    bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
    munmap((void *)bmdc_axi_lites, 0x10000);
    
    //gettimeofday(&end_time, NULL);
    if (end_time.tv_usec < start_time.tv_usec) {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 11000000 + end_time.tv_usec - start_time.tv_usec);
    }
    else {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
    }
    return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    return(y);
}

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
    int y;

    y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
    if (y<0)
        y = 0;
    else if (y>255)
        y = 255;
    return(y);
}

// 文字列が16進数かを調べる
int chkhex(char *str){
    while (*str != '\0'){
        if (!isxdigit(*str))
            return 0;
        str++;
    }
    return 1;
}


Vivado HLS 2014.4 で高位合成する用のCソースコードはソフトウェアのCソースコードとは明らかに違うと思う。普通、memcpy() とか使うと思わないよね?
だから、ソフトウェアのCソースコードのラプラシアンフィルタのみの処理時間とVivado HLS 2014.4 でIP 化したハードウェアのラプラシアンフィルタのみの処理時間を比較してもよいのじゃないかと車を運転しながら、そう思った。比較してみよう。
ソフトウェアのCソースコードのラプラシアンフィルタのみの処理時間は、laplacian_filter1 の処理時間と laplacian_filter2, laplacian_filter3 の処理時間を比較してみよう。

・laplacian_filter1 の処理時間と laplacian_filter2 の処理時間の比較
448 ms / 80.0 ms = 5.60 倍

・laplacian_filter1 の処理時間と laplacian_filter3 の処理時間の比較
448 ms / 60.0 ms ≒ 7.47 倍

memcpy() を使わないとAXI4バスのバースト・アクセスが使えないので、当然Vivado HLS では、それを使ってCソースコードを書く。それをソフトウェアとしてみた時に、私は違和感を覚える。でも、それはソフトウェアとしても動くし、ラプラシアンフィルタの処理が正常にできる。
ソフトウェアとハードウェアの比較はどのレベルで行うのが良いのか?悩む。
そう言えば、やっていないことがあった。”ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける”のCソースコードでVivado HLS 2014.4 でIP 化してみることだ。memcpy() を使っていないので、AXI4バスはバースト・アクセスが出来ないと思うが、果たしてどのくらいの性能が出るものか?とっても興味がある。
  1. 2015年06月29日 06:45 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0