////////////////////////////////////////////////////////////////////////// // // memspeed.c++ // // Benchmark program for CPU memory access. // // Copyright 1997, Silicon Graphics, Inc. // ALL RIGHTS RESERVED // // UNPUBLISHED -- Rights reserved under the copyright laws of the United // States. Use of a copyright notice is precautionary only and does not // imply publication or disclosure. // // U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: // Use, duplication or disclosure by the Government is subject to restrictions // as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights // in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or // in similar or successor clauses in the FAR, or the DOD or NASA FAR // Supplement. Contractor/manufacturer is Silicon Graphics, Inc., // 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. // // THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY // INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, // DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY // PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON // GRAPHICS, INC. // //////////////////////////////////////////////////////////////////////// #include // assert() #include // cachectl(), UNCACHEABLE #include // plock(), PROCLOCK #include // schedctl(), NDPRI, NDPHIMAX #include // stamp_t #include // dmGetUST #include // printf() #include // malloc() #include // bcopy() #define BUFFER_SIZE (1024 * 1024 * 2) #define TEST_COUNT 50 #define PAGE_SIZE 16384 //////// // // getUST // //////// stamp_t getUST( ) { unsigned long long ust; dmGetUST( &ust ); return (stamp_t) ust; } //////// // // rate // //////// float rate( stamp_t startTime, stamp_t endTime ) { stamp_t duration_nanos = (endTime - startTime); float duration = duration_nanos / 1000000000.0; float bytes = float(BUFFER_SIZE) * float(TEST_COUNT); return bytes / duration / 1000000.0; // MB/s } //////// // // testReadWrite // //////// void testReadWrite( void* buffer, const char* bufferType ) { // // Test reading in bytes, words, and long words. // stamp_t time1 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint8_t* ptr = (uint8_t*) buffer; /* REFERENCED */ uint8_t tmp; for ( int j = 0; j < BUFFER_SIZE; j++ ) { tmp = *ptr++; } } } stamp_t time2 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint32_t* ptr = (uint32_t*) buffer; /* REFERENCED */ uint32_t tmp; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint32_t); j++ ) { tmp = *ptr++; } } } stamp_t time3 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint64_t* ptr = (uint64_t*) buffer; /* REFERENCED */ uint64_t tmp; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint64_t); j++ ) { tmp = *ptr++; } } } // // Test writing bytes, words, and longwords. // stamp_t time4 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { uint8_t* ptr = (uint8_t*) buffer; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint8_t); j++ ) { *ptr++ = 0; } } } stamp_t time5 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { uint32_t* ptr = (uint32_t*) buffer; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint32_t); j++ ) { *ptr++ = 0; } } } stamp_t time6 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { uint64_t* ptr = (uint64_t*) buffer; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint64_t); j++ ) { *ptr++ = 0; } } } stamp_t time7 = getUST(); // // Print results // printf( " read %s\n", bufferType ); printf( " bytes: %7.3f MB/s\n", rate( time1, time2 ) ); printf( " 32-bit ints: %7.3f MB/s\n", rate( time2, time3 ) ); printf( " 64-bit ints: %7.3f MB/s\n", rate( time3, time4 ) ); printf( "\n" ); printf( " write %s\n", bufferType ); printf( " bytes: %7.3f MB/s\n", rate( time4, time5 ) ); printf( " 32-bit ints: %7.3f MB/s\n", rate( time5, time6 ) ); printf( " 64-bit ints: %7.3f MB/s\n", rate( time6, time7 ) ); printf( "\n" ); } //////// // // testCopy // //////// void testCopy( void* src, void* dst, const char* bufferTypes ) { // // Test bytes, words, and longwords // stamp_t time1 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint8_t* srcPtr = (uint8_t*) src; volatile uint8_t* dstPtr = (uint8_t*) dst; for ( int j = 0; j < BUFFER_SIZE; j++ ) { *dstPtr++ = *srcPtr++; } } } stamp_t time2 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint32_t* srcPtr = (uint32_t*) src; volatile uint32_t* dstPtr = (uint32_t*) dst; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint32_t); j++ ) { *dstPtr++ = *srcPtr++; } } } stamp_t time3 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { volatile uint64_t* srcPtr = (uint64_t*) src; volatile uint64_t* dstPtr = (uint64_t*) dst; for ( int j = 0; j < BUFFER_SIZE / sizeof(uint64_t); j++ ) { *dstPtr++ = *srcPtr++; } } } stamp_t time4 = getUST(); { for ( int i = 0; i < TEST_COUNT; i++ ) { bcopy( src, dst, BUFFER_SIZE ); } } stamp_t time5 = getUST(); // // Print results // printf( " copy %s\n", bufferTypes ); printf( " bytes: %7.3f MB/s\n", rate( time1, time2 ) ); printf( " 32-bit ints: %7.3f MB/s\n", rate( time2, time3 ) ); printf( " 64-bit ints: %7.3f MB/s\n", rate( time3, time4 ) ); printf( " bcopy: %7.3f MB/s\n", rate( time4, time5 ) ); printf( "\n" ); } //////// // // main // //////// main( ) { #if (_MIPS_ISA == _MIPS_ISA_MIPS4) printf( "Using 64-bit load and store instructions.\n\n" ); #else printf( "NOT USING 64-BIT LOAD AND STORE INSTRUCTIONS.\n\n" ); #endif // // Run at top priority. // { int status = schedctl( NDPRI, 0, NDPHIMAX ); if ( status == -1 ) { printf( "Could not set non-degrading high priority\n" ); exit( 1 ); } } // // Don't swap. // { int status = plock( PROCLOCK ); if ( status != 0 ) { printf( "Could not lock process into memory.\n" ); exit( 1 ); } } // // Allocate a cached buffer. // void* cached1 = malloc( BUFFER_SIZE ); assert( cached1 != NULL ); void* cached2 = malloc( BUFFER_SIZE ); assert( cached2 != NULL ); // // Allocate an uncached buffer. Round the address up to a page // boundary so that cachectl will accept it. // void* uncached1 = malloc( BUFFER_SIZE + PAGE_SIZE * 2 ); assert( uncached1 != NULL ); uncached1 = (void*) ( ( ((uint32_t)uncached1) + PAGE_SIZE - 1 ) / PAGE_SIZE * PAGE_SIZE ); { int s = cachectl( uncached1, BUFFER_SIZE, UNCACHEABLE ); assert( s == 0 ); } void* uncached2 = malloc( BUFFER_SIZE + PAGE_SIZE * 2 ); assert( uncached2 != NULL ); uncached2 = (void*) ( ( ((uint32_t)uncached2) + PAGE_SIZE - 1 ) / PAGE_SIZE * PAGE_SIZE ); { int s = cachectl( uncached2, BUFFER_SIZE, UNCACHEABLE ); assert( s == 0 ); } // // Run the tests // testReadWrite( cached1, "cached" ); testReadWrite( uncached1, "uncached" ); testCopy( cached1, cached2, " cached to cached" ); testCopy( cached1, uncached2, " cached to uncached" ); testCopy( uncached1, cached2, "uncached to cached" ); testCopy( uncached1, uncached2, "uncached to uncached" ); free( cached1 ); free( cached2 ); free( uncached2 ); free( uncached2 ); }