zynq操作系统:DDR带宽测试

本文涉及的产品
图片翻译,图片翻译 100张
文本翻译,文本翻译 100万字符
语种识别,语种识别 100万字符
简介: 个别时候,嵌入式设备的DDR除了常规的遍历读写和压力测试外,会有提供读写带宽的需求,下面介绍一种没有精确要求的测法,参考自http://github.com/raas/mbw

引言

 个别时候,嵌入式设备的DDR除了常规的遍历读写和压力测试外,会有提供读写带宽的需求,下面介绍一种没有精确要求的测法,参考自http://github.com/raas/mbw

 原理主要分三部分:memcpy(内存拷贝),dumb(字符拷贝),memblock(内存块)拷贝,通过计算拷贝指定内容的时间来得出内存拷贝速度,时间由系统函数gettimeofday()获得。

gettimeofday():

 它获得的时间精确到微秒(1e-6 s)量级。在一段代码前后分别使用gettimeofday可以计算代码执行时间:

struct timeval tv_begin, tv_end;
  gettimeofday(&tv_begin, NULL);
  foo();
  gettimeofday(&tv_end, NULL);

 函数执行成功后返回0,失败后返回-1,错误代码存于errno中。

/*
 * vim: ai ts=4 sts=4 sw=4 cinoptions=>4 expandtab
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
/* how many runs to average by default */
#define DEFAULT_NR_LOOPS 10
/* we have 3 tests at the moment */
#define MAX_TESTS 3
/* default block size for test 2, in bytes */
#define DEFAULT_BLOCK_SIZE 262144
/* test types */
#define TEST_MEMCPY 0
#define TEST_DUMB 1
#define TEST_MCBLOCK 2
/* version number */
#define VERSION "1.4"
/*
 * MBW memory bandwidth benchmark
 *
 * 2006, 2012 Andras.Horvath@gmail.com
 * 2013 j.m.slocum@gmail.com
 * (Special thanks to Stephen Pasich)
 *
 * http://github.com/raas/mbw
 *
 * compile with:
 *    gcc -O -o mbw mbw.c
 *
 * run with eg.:
 *
 *    ./mbw 300
 *
 * or './mbw -h' for help
 *
 * watch out for swap usage (or turn off swap)
 */
void usage()
{
    printf("mbw memory benchmark v%s, https://github.com/raas/mbw\n", VERSION);
    printf("Usage: mbw [options] array_size_in_MiB\n");
    printf("Options:\n");
    printf("  -n: number of runs per test (0 to run forever)\n");
    printf("  -a: Don't display average\n");
    printf("  -t%d: memcpy test\n", TEST_MEMCPY);
    printf("  -t%d: dumb (b[i]=a[i] style) test\n", TEST_DUMB);
    printf("  -t%d: memcpy test with fixed block size\n", TEST_MCBLOCK);
    printf("  -b <size>: block size in bytes for -t2 (default: %d)\n", DEFAULT_BLOCK_SIZE);
    printf("  -q: quiet (print statistics only)\n");
    printf("(will then use two arrays, watch out for swapping)\n");
    printf("'Bandwidth' is amount of data copied over the time this operation took.\n");
    printf("\nThe default is to run all tests available.\n");
}
/* ------------------------------------------------------ */
/* allocate a test array and fill it with data
 * so as to force Linux to _really_ allocate it */
long *make_array(unsigned long long asize)
{
    unsigned long long t;
    unsigned int long_size=sizeof(long);
    long *a;
    a=calloc(asize, long_size);
    if(NULL==a) {
        perror("Error allocating memory");
        exit(1);
    }
    /* make sure both arrays are allocated, fill with pattern */
    for(t=0; t<asize; t++) {
        a[t]=0xaa;
    }
    return a;
}
/* actual benchmark */
/* asize: number of type 'long' elements in test arrays
 * long_size: sizeof(long) cached
 * type: 0=use memcpy, 1=use dumb copy loop (whatever GCC thinks best)
 *
 * return value: elapsed time in seconds
 */
double worker(unsigned long long asize, long *a, long *b, int type, unsigned long long block_size)
{
    unsigned long long t;
    struct timeval starttime, endtime;
    double te;
    unsigned int long_size=sizeof(long);
    /* array size in bytes */
    unsigned long long array_bytes=asize*long_size;
    if(type==TEST_MEMCPY) { /* memcpy test */
        /* timer starts */
        gettimeofday(&starttime, NULL);
        memcpy(b, a, array_bytes);
        /* timer stops */
        gettimeofday(&endtime, NULL);
    } else if(type==TEST_MCBLOCK) { /* memcpy block test */
        char* aa = (char*)a;
        char* bb = (char*)b;
        gettimeofday(&starttime, NULL);
        for (t=array_bytes; t >= block_size; t-=block_size, aa+=block_size){
            bb=mempcpy(bb, aa, block_size);
        }
        if(t) {
            bb=mempcpy(bb, aa, t);
        }
        gettimeofday(&endtime, NULL);
    } else if(type==TEST_DUMB) { /* dumb test */
        gettimeofday(&starttime, NULL);
        for(t=0; t<asize; t++) {
            b[t]=a[t];
        }
        gettimeofday(&endtime, NULL);
    }
    te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
    return te;
}
/* ------------------------------------------------------ */
/* pretty print worker's output in human-readable terms */
/* te: elapsed time in seconds
 * mt: amount of transferred data in MiB
 * type: see 'worker' above
 *
 * return value: -
 */
void printout(double te, double mt, int type)
{
    switch(type) {
        case TEST_MEMCPY:
            printf("Method: MEMCPY\t");
            break;
        case TEST_DUMB:
            printf("Method: DUMB\t");
            break;
        case TEST_MCBLOCK:
            printf("Method: MCBLOCK\t");
            break;
    }
    printf("Elapsed: %.5f\t", te);
    printf("MiB: %.5f\t", mt);
    printf("Copy: %.3f MiB/s\n", mt/te);
    return;
}
/* ------------------------------------------------------ */
int main(int argc, char **argv)
{
    unsigned int long_size=0;
    double te, te_sum; /* time elapsed */
    unsigned long long asize=0; /* array size (elements in array) */
    int i;
    long *a, *b; /* the two arrays to be copied from/to */
    int o; /* getopt options */
    unsigned long testno;
    /* options */
    /* how many runs to average? */
    int nr_loops=DEFAULT_NR_LOOPS;
    /* fixed memcpy block size for -t2 */
    unsigned long long block_size=DEFAULT_BLOCK_SIZE;
    /* show average, -a */
    int showavg=1;
    /* what tests to run (-t x) */
    int tests[MAX_TESTS];
    double mt=0; /* MiBytes transferred == array size in MiB */
    int quiet=0; /* suppress extra messages */
    tests[0]=0;
    tests[1]=0;
    tests[2]=0;
    while((o=getopt(argc, argv, "haqn:t:b:")) != EOF) {
        switch(o) {
            case 'h':
                usage();
                exit(1);
                break;
            case 'a': /* suppress printing average */
                showavg=0;
                break;
            case 'n': /* no. loops */
                nr_loops=strtoul(optarg, (char **)NULL, 10);
                break;
            case 't': /* test to run */
                testno=strtoul(optarg, (char **)NULL, 10);
                if(testno>MAX_TESTS-1) {
                    printf("Error: test number must be between 0 and %d\n", MAX_TESTS-1);
                    exit(1);
                }
                tests[testno]=1;
                break;
            case 'b': /* block size in bytes*/
                block_size=strtoull(optarg, (char **)NULL, 10);
                if(0>=block_size) {
                    printf("Error: what block size do you mean?\n");
                    exit(1);
                }
                break;
            case 'q': /* quiet */
                quiet=1;
                break;
            default:
                break;
        }
    }
    /* default is to run all tests if no specific tests were requested */
    if( (tests[0]+tests[1]+tests[2]) == 0) {
        tests[0]=1;
        tests[1]=1;
        tests[2]=1;
    }
    if( nr_loops==0 && ((tests[0]+tests[1]+tests[2]) != 1) ) {
        printf("Error: nr_loops can be zero if only one test selected!\n");
        exit(1);
    }
    if(optind<argc) {
        mt=strtoul(argv[optind++], (char **)NULL, 10);
    } else {
        printf("Error: no array size given!\n");
        exit(1);
    }
    if(0>=mt) {
        printf("Error: array size wrong!\n");
        exit(1);
    }
    /* ------------------------------------------------------ */
    long_size=sizeof(long); /* the size of long on this platform */
    asize=1024*1024/long_size*mt; /* how many longs then in one array? */
    if(asize*long_size < block_size) {
        printf("Error: array size larger than block size (%llu bytes)!\n", block_size);
        exit(1);
    }
    if(!quiet) {
        printf("Long uses %d bytes. ", long_size);
        printf("Allocating 2*%lld elements = %lld bytes of memory.\n", asize, 2*asize*long_size);
        if(tests[2]) {
            printf("Using %lld bytes as blocks for memcpy block copy test.\n", block_size);
        }
    }
    a=make_array(asize);
    b=make_array(asize);
    /* ------------------------------------------------------ */
    if(!quiet) {
        printf("Getting down to business... Doing %d runs per test.\n", nr_loops);
    }
    /* run all tests requested, the proper number of times */
    for(testno=0; testno<MAX_TESTS; testno++) {
        te_sum=0;
        if(tests[testno]) {
            for (i=0; nr_loops==0 || i<nr_loops; i++) {
                te=worker(asize, a, b, testno, block_size);
                te_sum+=te;
                printf("%d\t", i);
                printout(te, mt, testno);
            }
            if(showavg) {
                printf("AVG\t");
                printout(te_sum/nr_loops, mt, testno);
            }
        }
    }
    free(a);
    free(b);
    return 0;
}

交叉编译

运行测试

常用参数

-q 隐藏日志

-n 10 测试次数

128 内存大小(单位是M)

执行结果如下图,其中主要关注AVG一行,内存分配速率越大,性能越好:

#./ddrtest -n 10 128
Long uses4bytes.Allocating 2*33554432 elements = 268435456 bytes of memory. Using 262144 bytes as blocks for memcpy block copy test. Getting down to business... Doing 10 runs per test.
Method:MEMCPY Elapsed:0.23141 MiB:128.00000 Copy: 553.133 MiB/s 
Metho0: MEMCPY  Elapsed: 0.23103  MiB:128.00000 Copy: 554.029 MiB/s 
Method:|  MEMCPY  Elapsed:0.23167 MiB:128.00000 Copy:552.500 MiB/s  
Method:MEMCPY Elapsed:0.23131 MiB:128.00000 Copy: 553.380 MiB/s 
Method:MEMCPY Elapsed:0.23192 MiB:128.00000 Copy:551.917 MiB/s  
Method: MEMCPY  Elapsed:0.23118 MiB:128.00000 Copy: 553.684 MiB/s 
Method;MEMCPY Elapsed:0.23176 MiB:128.00000 Copy:552.303 MiB/s  
Metno0:MEMCPY Elapsed: 0.23161  MiB:128.00000 Copy: 552.641 MiB/s 
9 Method;MEMCPY Elapsed:0.23200 MiB:128.00000 Copy:551.731 MiB/s  
Method: MEMCPY  Elapsed:0.23154 MiB:128.00000 Copy: 
9
AVG Methog:MEMCPY Elapsed:0.23154 MiB:128.00000 Copy:




相关文章
|
15天前
|
弹性计算 运维 开发者
os-copilot-操作系统智能助手测试和总结
OS-copilot的深度测评,使用co提供的 -t自动开启agent通道,-f批量处理task任务,通道 | 参数的文件理解和解析。
|
15天前
|
运维 关系型数据库 MySQL
os-copilot安装_配置_功能测试全集
我是一位中级运维工程师,我平时工作会涉及到 各类服务器的 数据库 与 java环境配置 操作。 我顺利使用了OS Copilot的 -t -f | 功能,我的疑惑是不能在自动操作过程中直接给与脚本运行权限,必须需要自己运行一下 chmod 这个既然有了最高的权限,为什么就不能直接给与运行权限呢。 我认为 -t 功能有用,能解决后台运行基础命令操作。 我认为 -f 功能有用,可以通过task文件中撰写连续任务操作。 我认为 | 对文件理解上有很直接的解读,可以在理解新程序上有很大帮助。
159 84
|
3月前
|
运维 Prometheus 监控
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
|
14天前
|
人工智能 Ubuntu Linux
os-copilot使用之全面配置与使用测试
作为一名个人开发者,我主要从事云服务器架设工作。近期,我成功使用了OS Copilot的 `-t -f |` 功能,解决了执行语句、连续提问及快速理解文件的问题。我发现这些功能非常实用,特别是在使用Workbench时能快速调用AI助手。此外,建议将AI功能与xShell工具联动,进一步提升效率。文中详细记录了购买服务器、远程连接、安装配置OS Copilot以及具体命令测试的过程,展示了如何通过快捷键和命令行操作实现高效开发。
112 67
|
16天前
|
弹性计算 运维 监控
OS Copilot-操作系统智能助手测试报告-新人体验
测试体验OS copilo安装、启动,体验copilot的提供的`-t`、`-f`、`|`通道的指令在在精准分析、批量任务处理、文件分析的能力。并记录下来。
157 18
|
10天前
|
弹性计算 运维 Java
OS-Copilot参数功能全面测试报告
作为一名运维工程师,我主要负责云资源的运维和管理。通过使用OS Copilot的-t/-f/管道功能,我顺利解决了环境快速搭建的问题,例如Tomcat的快速部署。具体步骤包括购买ECS服务器、配置安全组、远程登录并安装OS Copilot。使用-f参数成功安装并启动Tomcat,自动配置JDK,并通过|管道功能验证了生成内容的正确性。整个过程非常流畅,极大提升了工作效率。
37 12
|
10天前
|
弹性计算 Ubuntu Java
OS-Copilot-ubuntu镜像版本的具体测试使用(安装方式有单独注明)
作为一名个人开发者,我主要负责云资源的运维和管理。在使用OS Copilot的过程中,我遇到了一些配置问题,特别是在ECS实例中设置AccessKey时,但最终成功解决了。通过使用OS Copilot的-t/-f/管道功能,我大大提升了效率,减少了命令编写的工作量,特别是在搭建Java运行环境时效果显著。此外,| 功能帮助我快速理解文档,整体体验非常流畅,推荐给其他开发者使用。
26 6
|
12天前
|
弹性计算 运维 自然语言处理
OS Copilot综合功能测试
作为一名初级运维工程师,我主要负责服务器的基础运维操作。最近使用了阿里云的OS Copilot工具,其 `-t`、`-f` 和 | 功能极大地提升了我的工作效率。 -t 功能帮助我查询环境状态,解决了许多配置问题。 -f 功能支持多任务处理,例如搭建并测试Nginx服务。 | 功能可辅助分析文件内容,简化了复杂日志和脚本的解读。 建议:希望未来版本中能合并 `-t` 和 `-f` 的功能,并添加直接获取最高权限操作的参数,进一步提升效率。
38 8
|
11天前
|
人工智能 运维 监控
os-copilot-操作系统智能助手-测试人员使用总结
os-copilot-操作系统智能助手`-t`、`-f`、`|`等功能的使用总结
|
15天前
|
弹性计算 运维 Ubuntu
os-copilot在Alibaba Cloud Linux镜像下的安装与功能测试
我顺利使用了OS Copilot的 -t -f 功能,我的疑惑是在换行的时候就直接进行提问了,每次只能写一个问题,没法连续换行更有逻辑的输入问题。 我认为 -t 管道 功能有用 ,能解决环境问题的连续性操作。 我认为 -f 管道 功能有用 ,可以单独创建可连续性提问的task问题。 我认为 | 对文件直接理解在新的服务器理解有很大的帮助。 此外,我还有建议 可以在非 co 的环境下也能进行连续性的提问。
54 7