// The contents of this file are subject to the BOINC 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://boinc.berkeley.edu/license_1.0.txt // // 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): // #ifdef _WIN32 #include "stdafx.h" #endif #ifndef _WIN32 #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SIGNAL_H #include #endif #endif #include "error_numbers.h" #include "message.h" #include "cpu_benchmark.h" #ifdef _WIN32 #include #include // for timing void CALLBACK stop_benchmark(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); UINT speed_timer_id; #else void stop_benchmark(int a); #endif #define D_LOOP_ITERS 1000000 #define I_LOOP_ITERS 1000000 #define MEM_SIZE 1000000 #define NUM_DOUBLES 28 #define NUM_INTS 28 #define CACHE_MIN 1024 // smallest cache (in words) #define CACHE_MAX 512*1024 // largest cache #define STRIDE_MIN 1 // smallest stride (in words) #define STRIDE_MAX 128 // largest stride #define SAMPLE 10 // to get a larger time sample #define SECS_PER_RUN 0.2 // run_benchmark is volatile so the test loops will notice changes // made by stop_test // static volatile bool run_benchmark; static double cpu_time() { return (double)clock()/(double)CLOCKS_PER_SEC; } static double cpu_time_diff(double start, double end) { // take wraparound into account // while (end < start) { end += (double)(0x80000000)/(double)CLOCKS_PER_SEC; } return end-start; } //#define RUN_TEST #ifdef RUN_TEST int main(void) { int cache_size; cache_size = check_cache_size(CACHE_MAX); run_benchmark_suite(4); return 0; } void run_benchmark_suite(double num_secs_per_test) { if (num_secs_per_test<0) { msg_printf(NULL, MSG_ERROR, "error: run_benchmark_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", 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; double start, end, elapsed; //clock_t total_sec, sec; double nanosecs, temp2; int not_found; if (mem_size<0) { msg_printf(NULL, MSG_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", (int)(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", (int)(csize*sizeof(int)/CACHE_MIN)); not_found = 1; } i++; csize *= 2; } free(memBlock); 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