Changeset 877
- Timestamp:
- Aug 29, 2011, 7:02:47 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Makefile.am
r785 r877 6 6 AUTOMAKE_OPTIONS = dist-bzip2 7 7 8 bench: 9 cd test && $(MAKE) $(AM_MAKEFLAGS) $@ 10 .PHONY: bench 11 -
trunk/src/half.cpp
r873 r877 197 197 } 198 198 199 /* Constructor from float. Uses the non-branching version because benchmarks 200 * indicate it is always twice as fast. The penalty of loading the lookup 201 * tables does not seem important. */ 199 202 half half::makefast(float f) 200 203 { … … 203 206 } 204 207 208 /* Constructor from float with better precision. */ 205 209 half half::makeslow(float f) 206 210 { … … 209 213 } 210 214 215 /* Cast to float. Uses the branching version because loading the tables 216 * for only one value is going to be cache-expensive. */ 211 217 half::operator float() const 212 218 { 219 /* FIXME: there is a hidden "this" in this method. Export more 220 * code so that it can all work in registers instead. */ 213 221 union { float f; uint32_t x; } u; 214 222 u.x = half_to_float_branch(bits); … … 216 224 } 217 225 218 size_t half::co py(half *dst, float const *src, size_t nelem)226 size_t half::convert(half *dst, float const *src, size_t nelem) 219 227 { 220 228 for (size_t i = 0; i < nelem; i++) … … 228 236 } 229 237 230 size_t half::co py(float *dst, half const *src, size_t nelem)238 size_t half::convert(float *dst, half const *src, size_t nelem) 231 239 { 232 240 for (size_t i = 0; i < nelem; i++) -
trunk/src/half.h
r874 r877 26 26 { 27 27 public: 28 /* Constructors. Always inline so that the code can work in registers 29 * instead of calling routines with the hidden "this" parameter. */ 28 30 inline half() { } 29 30 inline half(float f) 31 { 32 *this = makefast(f); 33 } 31 inline half(float f) { *this = makefast(f); } 34 32 35 33 inline int is_nan() const … … 58 56 59 57 /* Array conversions */ 60 static size_t co py(half *dst, float const *src, size_t nelem);61 static size_t co py(float *dst, half const *src, size_t nelem);58 static size_t convert(half *dst, float const *src, size_t nelem); 59 static size_t convert(float *dst, half const *src, size_t nelem); 62 60 63 61 /* Operations */ -
trunk/test/half.cpp
r875 r877 34 34 { 35 35 CPPUNIT_TEST_SUITE(HalfTest); 36 CPPUNIT_TEST(test_half_from_float); 37 CPPUNIT_TEST(test_half_makeslow); 36 38 CPPUNIT_TEST(test_half_makebits); 37 CPPUNIT_TEST(test_half_makeslow);38 CPPUNIT_TEST(test_half_makefast);39 39 CPPUNIT_TEST(test_half_is_nan); 40 40 CPPUNIT_TEST(test_half_is_inf); … … 57 57 void tearDown() {} 58 58 59 void test_half_ makebits()60 { 61 for ( unsigned int i = 0; i < 0x10000; i++)62 { 63 half a = half::makebits(i);64 uint16_t b = i;59 void test_half_from_float() 60 { 61 for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++) 62 { 63 half a = (half)pairs[i].f; 64 uint16_t b = pairs[i].x; 65 65 CPPUNIT_ASSERT_EQUAL(a.bits, b); 66 66 } … … 77 77 } 78 78 79 void test_half_make fast()80 { 81 for ( size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)82 { 83 half a = half::make fast(pairs[i].f);84 uint16_t b = pairs[i].x;79 void test_half_makebits() 80 { 81 for (unsigned int i = 0; i < 0x10000; i++) 82 { 83 half a = half::makebits(i); 84 uint16_t b = i; 85 85 CPPUNIT_ASSERT_EQUAL(a.bits, b); 86 86 } -
trunk/test/lol-bench.cpp
r872 r877 13 13 #endif 14 14 15 #include <cstdio> 16 15 17 #include "core.h" 16 18 #include "loldebug.h" … … 19 21 using namespace lol; 20 22 23 static size_t const HALF_TABLE_SIZE = 1024 * 1024; 24 static size_t const HALF_RUNS = 100; 25 26 static void bench_half(int mode); 27 21 28 int main(int argc, char **argv) 22 29 { 23 Timer timer; 30 Log::Info("-----------------------------------\n"); 31 Log::Info("Half precision floats (random bits)\n"); 32 Log::Info("-----------------------------------\n"); 33 bench_half(1); 24 34 25 float ftotal = 0.0f; 26 for (uint32_t i = 0; i < 0xffffffffu; i += 7) 27 { 28 union { float f; uint32_t x; } u; 29 u.x = i; 30 31 float h = (float)half::makefast(u.f); 32 ftotal += h; 33 } 34 Log::Info("time for makeslow: %f (hash %f)\n", timer.GetMs(), ftotal); 35 36 uint16_t total = 0; 37 for (uint32_t i = 0; i < 0xffffffffu; i += 7) 38 { 39 union { float f; uint32_t x; } u; 40 u.x = i; 41 42 half h = half::makeslow(u.f); 43 total ^= h.bits; 44 } 45 Log::Info("time for makeslow: %f (hash %04x)\n", timer.GetMs(), total); 46 47 for (uint32_t i = 0; i < 0xffffffffu; i += 7) 48 { 49 union { float f; uint32_t x; } u; 50 u.x = i; 51 52 half h = half::makefast(u.f); 53 total ^= h.bits; 54 } 55 Log::Info("time for makefast: %f (hash %04x)\n", timer.GetMs(), total); 35 Log::Info("---------------------------------\n"); 36 Log::Info("Half precision floats [-2.0, 2.0]\n"); 37 Log::Info("---------------------------------\n"); 38 bench_half(2); 56 39 57 40 return EXIT_SUCCESS; 58 41 } 59 42 43 static void bench_half(int mode) 44 { 45 float result[8] = { 0.0f }; 46 Timer timer; 47 48 /* Set up tables */ 49 float *pf = new float[HALF_TABLE_SIZE]; 50 half *ph = new half[HALF_TABLE_SIZE]; 51 52 switch (mode) 53 { 54 case 1: 55 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 56 ph[i] = half::makebits(rand()); 57 break; 58 case 2: 59 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 60 ph[i] = RandF(-2.0f, 2.0f); 61 break; 62 } 63 64 for (size_t run = 0; run < HALF_RUNS; run++) 65 { 66 /* Convert half to float (array) */ 67 timer.GetMs(); 68 half::convert(pf, ph, HALF_TABLE_SIZE); 69 result[1] += timer.GetMs(); 70 71 /* Convert half to float (fast) */ 72 timer.GetMs(); 73 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 74 pf[i] = (float)ph[i]; 75 result[0] += timer.GetMs(); 76 77 /* Convert float to half (array) */ 78 timer.GetMs(); 79 half::convert(ph, pf, HALF_TABLE_SIZE); 80 result[4] += timer.GetMs(); 81 82 /* Convert float to half (fast) */ 83 timer.GetMs(); 84 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 85 ph[i] = (half)pf[i]; 86 result[2] += timer.GetMs(); 87 88 /* Convert float to half (slow) */ 89 timer.GetMs(); 90 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 91 ph[i] = half::makeslow(pf[i]); 92 result[3] += timer.GetMs(); 93 94 /* Change sign of every half */ 95 timer.GetMs(); 96 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 97 ph[i] = -ph[i]; 98 result[5] += timer.GetMs(); 99 100 /* Add a half to every float */ 101 timer.GetMs(); 102 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 103 pf[i] += ph[i]; 104 result[6] += timer.GetMs(); 105 106 /* Add a float to every half */ 107 timer.GetMs(); 108 for (size_t i = 0; i < HALF_TABLE_SIZE; i++) 109 ph[i] += pf[i]; 110 result[7] += timer.GetMs(); 111 } 112 113 delete[]pf; 114 delete[]ph; 115 116 for (size_t i = 0; i < sizeof(result) / sizeof(*result); i++) 117 result[i] *= 1000000.0f / (HALF_TABLE_SIZE * HALF_RUNS); 118 119 Log::Info(" ns/elem\n"); 120 Log::Info("float = half %7.3f\n", result[0]); 121 Log::Info("float[] = half[] %7.3f\n", result[1]); 122 Log::Info("half = float %7.3f\n", result[2]); 123 Log::Info("half = makeslow(float) %7.3f\n", result[3]); 124 Log::Info("half[] = float[] %7.3f\n", result[4]); 125 Log::Info("half = -half %7.3f\n", result[5]); 126 Log::Info("float += half %7.3f\n", result[6]); 127 Log::Info("half += float %7.3f\n", result[7]); 128 } 129
Note: See TracChangeset
for help on using the changeset viewer.