diff options
author | 2010-06-21 11:59:37 +0200 | |
---|---|---|
committer | 2010-06-21 11:59:37 +0200 | |
commit | e54635da11f3c7c3daf2a06fbe64928d60aa900e (patch) | |
tree | 6a560b04bcbb90bd773cd63c790c55bd93eb9301 /Eigen | |
parent | 7196777b746ab652c981681dbe0c5e314cb36b64 (diff) |
add functions to query the L1 and L2/L3 cache sizes
Diffstat (limited to 'Eigen')
-rw-r--r-- | Eigen/src/Core/util/Memory.h | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index c67b9774f..1b1ef6712 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -1,10 +1,11 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr> +// Copyright (C) 2008-2010 Gael Guennebaud <g.gael@free.fr> // Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com> // Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com> // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com> +// Copyright (C) 2010 Thomas Capricelli <orzel@freehackers.org> // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -584,4 +585,72 @@ public: { return true; } }; +//---------- Cache sizes ---------- + +#if defined(__GNUC__) +# if defined(__PIC__) && defined(__i386__) +# define EIGEN_CPUID(abcd,func) \ + __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func)); +# else +# define EIGEN_CPUID(abcd,func) \ + __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func) ); +# endif +#elif defined(_MSC_VER) +# define EIGEN_CPUID(abcd,func) __cpuid((int*)abcd,func) +#endif + +/** \internal + * \returns the size in Bytes of the L1 data cache */ +inline std::ptrdiff_t ei_fetchL1CacheSize() +{ + int abcd[4]; + + // try the direct method using extended level + EIGEN_CPUID(abcd,0x80000005); + std::ptrdiff_t l1 = std::ptrdiff_t(abcd[2] >> 24) * 1024; + + if(l1>0) + return l1*1024; + + // it fails, try using the standard level + EIGEN_CPUID(abcd,0x00000002); + unsigned char * bytes = reinterpret_cast<unsigned char *>(abcd)+2; + for(int i=0; i<14; ++i) + { + switch(bytes[i]) + { + case 0x0A: l1 = 8; break; // 0Ah data L1 cache, 8 KB, 2 ways, 32 byte lines + case 0x0C: l1 = 16; break; // 0Ch data L1 cache, 16 KB, 4 ways, 32 byte lines + case 0x0E: l1 = 24; break; // 0Eh data L1 cache, 24 KB, 6 ways, 64 byte lines + case 0x10: l1 = 16; break; // 10h data L1 cache, 16 KB, 4 ways, 32 byte lines (IA-64) + case 0x15: l1 = 16; break; // 15h code L1 cache, 16 KB, 4 ways, 32 byte lines (IA-64) + case 0x2C: l1 = 32; break; // 2Ch data L1 cache, 32 KB, 8 ways, 64 byte lines + case 0x30: l1 = 32; break; // 30h code L1 cache, 32 KB, 8 ways, 64 byte lines +// 56h L0 data TLB, 4M pages, 4 ways, 16 entries +// 57h L0 data TLB, 4K pages, 4 ways, 16 entries +// 59h L0 data TLB, 4K pages, fully, 16 entries + case 0x60: l1 = 16; break; // 60h data L1 cache, 16 KB, 8 ways, 64 byte lines, sectored + case 0x66: l1 = 8; break; // 66h data L1 cache, 8 KB, 4 ways, 64 byte lines, sectored + case 0x67: l1 = 16; break; // 67h data L1 cache, 16 KB, 4 ways, 64 byte lines, sectored + case 0x68: l1 = 32; break; // 68h data L1 cache, 32 KB, 4 ways, 64 byte lines, sectored +// 77h code L1 cache, 16 KB, 4 ways, 64 byte lines, sectored (IA-64) +// 96h data L1 TLB, 4K...256M pages, fully, 32 entries (IA-64) + default: break; + } + } + + return l1*1024; +} + +/** \internal + * \returns the size in Bytes of the L2 or L3 cache if this later is present */ +inline std::ptrdiff_t ei_fetchTopLevelCacheSize() +{ + int abcd[4]; + EIGEN_CPUID(abcd,0x80000006); + std::ptrdiff_t l2 = std::ptrdiff_t(abcd[2] >> 16) * 1024; + std::ptrdiff_t l3 = std::ptrdiff_t((abcd[3] & 0xFFFC000) >> 18) * 512 * 1024; + return std::max(l2,l3); +} + #endif // EIGEN_MEMORY_H |