内存延时测试
2019-10-11 本文已影响0人
yanfeizhang
#include <stdlib.h>
#include <stdio.h>
#include "clock.h" /* routines to access the cycle counter */
#define MINBYTES (1 << 11) /* Working set size ranges from 2 KB */
#define MAXBYTES (1 << 26) /* ... up to 64 MB */
#define MAXSTRIDE 64 /* Strides range from 1 to 64 elems */
#define MAXELEMS MAXBYTES/sizeof(double)
#define ASIZE (1 << 17)
double data[MAXELEMS]; /* The global array we'll be traversing */
/* start declare functions */
void init_data(double *data, int n);
void run_delay_testing();
double get_seque_access_result(int size, int stride, int type);
double get_random_access_result(int size, int type);
/* end declare functions */
int main()
{
init_data(data, MAXELEMS);
printf("Delay (ns)\n");
run_delay_testing();
printf("\n\n");
exit(0);
}
void run_delay_testing(){
int size; /* Working set size (in bytes) */
int stride; /* Stride (in array elements) */
/*Print the size header */
printf("\t");
for (size = MAXBYTES; size >= MINBYTES; size >>= 1) {
if (size > (1 << 20)){
printf("%dm\t", size / (1 << 20));
}else{
printf("%dk\t", size / 1024);
}
}
printf("\n");
/* estmate the band width sequencely */
for (stride = 1; stride <= MAXSTRIDE; stride=stride+1) {
printf("s%d\t", stride);
for (size = MAXBYTES; size >= MINBYTES; size >>= 1) {
printf("%.2f\t", get_seque_access_result(size, stride, 1));
}
printf("\n");
}
/* estmate the band width real randomly*/
printf("\random\t");
for (size = MAXBYTES; size >= MINBYTES; size >>= 1) {
printf("%.2f\t", get_random_access_result(size,1));
}
printf("\n");
}
/* $end mountainmain */
/* init_data - initializes the array */
void init_data(double *data, int n)
{
int i;
for (i = 0; i < n; i++)
data[i] = i;
}
void create_rand_array(int max, int count, int* pArr)
{
int i;
for (i = 0; i < count; i ++,pArr++) {
int rd = rand();
int randRet = (long int)rd * max / RAND_MAX;
*pArr = randRet;
}
return;
}
/*
* seque_access
* - access global data array step by step
*/
void seque_access(int elems, int stride) /* The test function */
{
int i;
double result = 0.0;
volatile double sink;
for (i = 0; i < elems; i += stride) {
result += data[i];
}
sink = result; /* So compiler doesn't optimize away the loop */
}
/*
* random_access
* - access global by random way indexed by random_index_arr
*/
void random_access(int* random_index_arr, int count) /* The test function */
{
int i;
double result = 0.0;
volatile double sink;
for (i = 0; i < count; i++) {
result += data[*(random_index_arr+i)];
}
sink = result; /* So compiler doesn't optimize away the loop */
}
/*
* get_random_access_result : test the computer storage(register,cache or memory) band width.
* - size: data size will be tested
* - stride: steps
* - type: 0 get the band width,
* - 1 get the consumed cpu cycles per operation.
*/
double get_seque_access_result(int size, int stride, int type)
{
int i;
long int operations;
long int total_accessed_bytes;
long int used_microseconds;
int samples = 1000;
int elems = size / sizeof(double);
/* run the test*/
start_timer();
for(i=0; i<samples; i++){
seque_access(elems, stride);
}
used_microseconds = get_timer();
if(0==used_microseconds){
return 0;
}
/* analysize result*/
operations = (long int)samples * (long int)elems / stride;
total_accessed_bytes = operations * sizeof(double);
double result = 0;
if(0==type){ /* get width */
/* width = size(M)/ time(s)
= (total_accessed_bytes / 1000000) / (used / 1000000000)
= total_accessed_bytes*1000/used_microseconds;
*/
result = total_accessed_bytes * 1000 / used_microseconds;
}else if(1==type){/* get cycles_per_operation */
result = (double)used_microseconds/operations;
}
return result;
}
/*
* get_random_access_result : test the computer storage(register,cache or memory) band width.
* - size: data size will be tested
* - type: 0 get the band width,
* - 1 get the consumed cpu cycles per operation.
*/
double get_random_access_result(int size, int type)
{
int i;
int *p;
long int operations;
long int total_accessed_bytes;
long int used_microseconds;
int samples = 300;
int elems = size / sizeof(double);
int access_count = elems;
/* prepare for random access*/
int* random_access_arr = malloc(access_count*sizeof(int));
for(i=0,p=random_access_arr; i<access_count; i++,p++){
*p = 0;
}
create_rand_array(elems, access_count, random_access_arr);
/* run the test*/
start_timer();
for(i=0; i<samples; i++){
random_access(random_access_arr, access_count);
}
used_microseconds = get_timer();
/* analysize result*/
operations = (long int)samples * (long int)access_count;
total_accessed_bytes = operations * sizeof(double);
double result = 0;;
if(0==type){ /* get width */
/* width = size(M)/ time(s)
= (total_accessed_bytes / 1000000) / (used / 1000000000)
= total_accessed_bytes*1000/used_microseconds;
*/
result = total_accessed_bytes * 1000 / used_microseconds;
}else if(1==type){/* get cycles_per_operation */
result = used_microseconds/operations*2.4;
}
return result;
}
/* $end mountainfuns */