// The contents of this file are subject to the Mozilla Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // #include #include #include #include #include "speed_stats.h" #include "error_numbers.h" // # of iterations of each test to run for initial timing purposes #define D_FLOP_ITERS 100 #define I_OP_ITERS 100 #define BANDWIDTH_ITERS 5 //#define RUN_TEST #ifdef RUN_TEST int main(void) { int cache_size; cache_size = check_cache_size(CACHE_MAX); run_test_suite(4); return 0; } void run_test_suite(double num_secs_per_test) { if (num_secs_per_test<0) { fprintf(stderr, "error: run_test_suite: negative num_seconds_per_test\n"); } printf( "Running tests. This will take about %.1lf seconds.\n\n", num_secs_per_test*3 ); printf( "Speed: %.5lf million flops/sec\n\n", run_double_prec_test(num_secs_per_test)/1000000 ); printf( "Speed: %.5lf million integer ops/sec\n\n", run_int_test(num_secs_per_test)/1000000 ); printf( "Speed: %.5lf MB/sec\n\n", 12*sizeof(double)*run_mem_bandwidth_test(num_secs_per_test)/1000000 ); } #endif int check_cache_size(int mem_size) { int i, n, index, stride, *memBlock, logStride, logCache; double **results; int steps, tsteps, csize, limit, temp, cind, sind; clock_t total_sec, sec; double secs, nanosecs, temp2; int not_found; if (mem_size<0) { fprintf(stderr, "error: check_cache_size: negative mem_size\n"); return ERR_NEG; } logStride = (int)(log((double)(STRIDE_MAX/STRIDE_MIN))/log(2.0))+1; logCache = (int)(log((double)(CACHE_MAX/CACHE_MIN))/log(2.0))+1; printf("Test will take about %.2f seconds.\n", SECS_PER_RUN*logStride*logCache); results = (double **)malloc(sizeof(double *)*logStride); for (i=0;i0;n--) { results[i][n] /= results[i][n-1]; } } for (i=0;i 1.5) { printf("Level 2 Data Cache is %d KB.\n", csize*sizeof(int)/CACHE_MIN); not_found = 0; } if (not_found == 2 && results[0][i] > 1.5) { printf("Level 1 Data Cache is %d KB.\n", csize*sizeof(int)/CACHE_MIN); not_found = 1; } i++; csize *= 2; } free(memBlock); for (i=0;i D_FLOP_ITERS) { // no need to redo test if we already got enough df_test_time = (int)double_flop_test(df_iters, 0); } else { df_iters = D_FLOP_ITERS; } df_secs = (double)df_test_time/CLOCKS_PER_SEC; return 1000000*df_iters/df_secs; } // Run the test of integer math speed for about num_secs seconds // double run_int_test(double num_secs) { int int_test_time, int_iters; double int_secs; if (num_secs<0) { fprintf(stderr, "error: run_int_test: negative num_secs\n"); return ERR_NEG; } // Start by doing some quick timing tests for rough calibration int_test_time = (int)int_op_test(I_OP_ITERS, 0); if (int_test_time <= 0) int_test_time = 1; int_secs = (double)int_test_time/CLOCKS_PER_SEC; // Calculate the # of iterations based on these tests int_iters = (int)(I_OP_ITERS*num_secs/int_secs); if (int_iters > I_OP_ITERS) { // no need to redo test int_test_time = (int)int_op_test(int_iters, 0); } else { int_iters = I_OP_ITERS; } int_secs = (double)int_test_time/CLOCKS_PER_SEC; return 1000000*int_iters/int_secs; } // Run the test of memory bandwidth speed for about num_secs seconds // double run_mem_bandwidth_test(double num_secs) { int bw_test_time; double bw_secs; int bw_iters; if (num_secs<0) { fprintf(stderr, "error: run_mem_bandwidth_test: negative num_secs\n"); return ERR_NEG; } // Start by doing some quick timing tests for rough calibration bw_test_time = (int)bandwidth_test(BANDWIDTH_ITERS, 0); if (bw_test_time <= 0) bw_test_time = 1; bw_secs = (double)bw_test_time/CLOCKS_PER_SEC; // Calculate the # of iterations based on these tests bw_iters = (int)(BANDWIDTH_ITERS*num_secs/bw_secs); if (bw_iters > BANDWIDTH_ITERS) { // no need to redo test bw_test_time = (int)bandwidth_test(bw_iters, 0); } else { bw_iters = BANDWIDTH_ITERS; } bw_secs = (double)bw_test_time/CLOCKS_PER_SEC; return 1000000*bw_iters/bw_secs; } // One iteration == D_LOOP_ITERS (1,000,000) floating point operations // If time_total is negative, there was an error in the calculation, // meaning there is probably something wrong with the CPU clock_t double_flop_test(int iterations, int print_debug) { double a[NUM_DOUBLES],t1,t2; double temp; clock_t time_start, time_total; int i,j,k,calc_error; if (iterations<0) { fprintf(stderr, "error: double_flop_test: negative iterations\n"); return ERR_NEG; } // Initialize the array a[0] = 1; for (i=1;i time_start) { time_total -= time_start; } else { time_total = 0; // this is just a kludge } calc_error = 0; temp = 1; // Check to make sure all the values are the same as when we started for (i=0;i=0;k--) { a[k] += 6; // 2 int ops } for (k=0;k=0;k--) { a[k] -= 2; // 4 int ops } for (k=NUM_INTS-1;k>0;k--) { a[k] -= a[k-1]; // 5 int ops } for (k=1;k0;k--) { if (a[k-1] != 0) // 7 int ops a[k] /= a[k-1]; // 8 int ops } for (k=1;k time_start) { time_total -= time_start; } else { time_total = 0; // this is just a kludge } calc_error = 0; temp = 1; // Check to make sure all the values are the same as when we started for (i=0;i time_start) { time_total -= time_start; } else { time_total = 0; // this is just a kludge } copy_error = 0; for (i=0;i