00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef EIGEN_MEMORY_H
00035 #define EIGEN_MEMORY_H
00036
00037
00038
00039
00040
00041
00042
00043
00044 #if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \
00045 && defined(__LP64__)
00046 #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 1
00047 #else
00048 #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 0
00049 #endif
00050
00051
00052
00053
00054
00055 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
00056 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
00057 #else
00058 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
00059 #endif
00060
00061 #if defined(__APPLE__) \
00062 || defined(_WIN64) \
00063 || EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED \
00064 || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
00065 #define EIGEN_MALLOC_ALREADY_ALIGNED 1
00066 #else
00067 #define EIGEN_MALLOC_ALREADY_ALIGNED 0
00068 #endif
00069
00070 #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
00071 && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
00072 #define EIGEN_HAS_POSIX_MEMALIGN 1
00073 #else
00074 #define EIGEN_HAS_POSIX_MEMALIGN 0
00075 #endif
00076
00077 #ifdef EIGEN_VECTORIZE_SSE
00078 #define EIGEN_HAS_MM_MALLOC 1
00079 #else
00080 #define EIGEN_HAS_MM_MALLOC 0
00081 #endif
00082
00083 namespace internal {
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 inline void* handmade_aligned_malloc(size_t size)
00095 {
00096 void *original = std::malloc(size+16);
00097 if (original == 0) return 0;
00098 void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
00099 *(reinterpret_cast<void**>(aligned) - 1) = original;
00100 return aligned;
00101 }
00102
00103
00104 inline void handmade_aligned_free(void *ptr)
00105 {
00106 if (ptr) std::free(*(reinterpret_cast<void**>(ptr) - 1));
00107 }
00108
00109
00110
00111
00112
00113
00114 inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
00115 {
00116 if (ptr == 0) return handmade_aligned_malloc(size);
00117 void *original = *(reinterpret_cast<void**>(ptr) - 1);
00118 original = std::realloc(original,size+16);
00119 if (original == 0) return 0;
00120 void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
00121 *(reinterpret_cast<void**>(aligned) - 1) = original;
00122 return aligned;
00123 }
00124
00125
00126
00127
00128
00129 void* aligned_malloc(size_t size);
00130 void aligned_free(void *ptr);
00131
00132
00133
00134
00135
00136
00137 inline void* generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
00138 {
00139 if (ptr==0)
00140 return aligned_malloc(size);
00141
00142 if (size==0)
00143 {
00144 aligned_free(ptr);
00145 return 0;
00146 }
00147
00148 void* newptr = aligned_malloc(size);
00149 if (newptr == 0)
00150 {
00151 #ifdef EIGEN_HAS_ERRNO
00152 errno = ENOMEM;
00153 #endif
00154 return 0;
00155 }
00156
00157 if (ptr != 0)
00158 {
00159 std::memcpy(newptr, ptr, std::min(size,old_size));
00160 aligned_free(ptr);
00161 }
00162
00163 return newptr;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 inline void* aligned_malloc(size_t size)
00174 {
00175 #ifdef EIGEN_NO_MALLOC
00176 eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00177 #endif
00178
00179 void *result;
00180 #if !EIGEN_ALIGN
00181 result = std::malloc(size);
00182 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00183 result = std::malloc(size);
00184 #elif EIGEN_HAS_POSIX_MEMALIGN
00185 if(posix_memalign(&result, 16, size)) result = 0;
00186 #elif EIGEN_HAS_MM_MALLOC
00187 result = _mm_malloc(size, 16);
00188 #elif (defined _MSC_VER)
00189 result = _aligned_malloc(size, 16);
00190 #else
00191 result = handmade_aligned_malloc(size);
00192 #endif
00193
00194 #ifdef EIGEN_EXCEPTIONS
00195 if(result == 0)
00196 throw std::bad_alloc();
00197 #endif
00198 return result;
00199 }
00200
00201
00202 inline void aligned_free(void *ptr)
00203 {
00204 #if !EIGEN_ALIGN
00205 std::free(ptr);
00206 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00207 std::free(ptr);
00208 #elif EIGEN_HAS_POSIX_MEMALIGN
00209 std::free(ptr);
00210 #elif EIGEN_HAS_MM_MALLOC
00211 _mm_free(ptr);
00212 #elif defined(_MSC_VER)
00213 _aligned_free(ptr);
00214 #else
00215 handmade_aligned_free(ptr);
00216 #endif
00217 }
00218
00219
00220
00221
00222
00223
00224 inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
00225 {
00226 EIGEN_UNUSED_VARIABLE(old_size);
00227
00228 void *result;
00229 #if !EIGEN_ALIGN
00230 result = std::realloc(ptr,new_size);
00231 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00232 result = std::realloc(ptr,new_size);
00233 #elif EIGEN_HAS_POSIX_MEMALIGN
00234 result = generic_aligned_realloc(ptr,new_size,old_size);
00235 #elif EIGEN_HAS_MM_MALLOC
00236
00237
00238
00239 #if defined(_MSC_VER) && defined(_mm_free)
00240 result = _aligned_realloc(ptr,new_size,16);
00241 #else
00242 result = generic_aligned_realloc(ptr,new_size,old_size);
00243 #endif
00244 #elif defined(_MSC_VER)
00245 result = _aligned_realloc(ptr,new_size,16);
00246 #else
00247 result = handmade_aligned_realloc(ptr,new_size,old_size);
00248 #endif
00249
00250 #ifdef EIGEN_EXCEPTIONS
00251 if (result==0 && new_size!=0)
00252 throw std::bad_alloc();
00253 #endif
00254 return result;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 template<bool Align> inline void* conditional_aligned_malloc(size_t size)
00265 {
00266 return aligned_malloc(size);
00267 }
00268
00269 template<> inline void* conditional_aligned_malloc<false>(size_t size)
00270 {
00271 #ifdef EIGEN_NO_MALLOC
00272 eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00273 #endif
00274
00275 void *result = std::malloc(size);
00276 #ifdef EIGEN_EXCEPTIONS
00277 if(!result) throw std::bad_alloc();
00278 #endif
00279 return result;
00280 }
00281
00282
00283 template<bool Align> inline void conditional_aligned_free(void *ptr)
00284 {
00285 aligned_free(ptr);
00286 }
00287
00288 template<> inline void conditional_aligned_free<false>(void *ptr)
00289 {
00290 std::free(ptr);
00291 }
00292
00293 template<bool Align> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
00294 {
00295 return aligned_realloc(ptr, new_size, old_size);
00296 }
00297
00298 template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
00299 {
00300 return std::realloc(ptr, new_size);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310 template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
00311 {
00312 for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
00313 return ptr;
00314 }
00315
00316
00317
00318
00319 template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
00320 {
00321
00322 if(ptr)
00323 while(size) ptr[--size].~T();
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 template<typename T> inline T* aligned_new(size_t size)
00335 {
00336 T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
00337 return construct_elements_of_array(result, size);
00338 }
00339
00340 template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
00341 {
00342 T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
00343 return construct_elements_of_array(result, size);
00344 }
00345
00346
00347
00348
00349 template<typename T> inline void aligned_delete(T *ptr, size_t size)
00350 {
00351 destruct_elements_of_array<T>(ptr, size);
00352 aligned_free(ptr);
00353 }
00354
00355
00356
00357
00358 template<typename T, bool Align> inline void conditional_aligned_delete(T *ptr, size_t size)
00359 {
00360 destruct_elements_of_array<T>(ptr, size);
00361 conditional_aligned_free<Align>(ptr);
00362 }
00363
00364 template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
00365 {
00366 T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
00367 if (new_size > old_size)
00368 construct_elements_of_array(result+old_size, new_size-old_size);
00369 return result;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 template<typename Scalar, typename Index>
00391 inline static Index first_aligned(const Scalar* array, Index size)
00392 {
00393 typedef typename packet_traits<Scalar>::type Packet;
00394 enum { PacketSize = packet_traits<Scalar>::size,
00395 PacketAlignedMask = PacketSize-1
00396 };
00397
00398 if(PacketSize==1)
00399 {
00400
00401
00402 return 0;
00403 }
00404 else if(size_t(array) & (sizeof(Scalar)-1))
00405 {
00406
00407
00408 return size;
00409 }
00410 else
00411 {
00412 return std::min<Index>( (PacketSize - (Index((size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
00413 & PacketAlignedMask, size);
00414 }
00415 }
00416
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 #if (defined __linux__)
00436 #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
00437 ? alloca(SIZE) \
00438 : Eigen::internal::aligned_malloc(SIZE)
00439 #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
00440 #elif defined(_MSC_VER)
00441 #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
00442 ? _alloca(SIZE) \
00443 : Eigen::internal::aligned_malloc(SIZE)
00444 #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
00445 #else
00446 #define ei_aligned_stack_alloc(SIZE) Eigen::internal::aligned_malloc(SIZE)
00447 #define ei_aligned_stack_free(PTR,SIZE) Eigen::internal::aligned_free(PTR)
00448 #endif
00449
00450 #define ei_aligned_stack_new(TYPE,SIZE) Eigen::internal::construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
00451 #define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {Eigen::internal::destruct_elements_of_array<TYPE>(PTR, SIZE); \
00452 ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
00453
00454
00455
00456
00457
00458
00459 #if EIGEN_ALIGN
00460 #ifdef EIGEN_EXCEPTIONS
00461 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00462 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00463 try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
00464 catch (...) { return 0; } \
00465 return 0; \
00466 }
00467 #else
00468 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00469 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00470 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00471 }
00472 #endif
00473
00474 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
00475 void *operator new(size_t size) { \
00476 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00477 } \
00478 void *operator new[](size_t size) { \
00479 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00480 } \
00481 void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00482 void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00483 \
00484 \
00485 \
00486 static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
00487 void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
00488 \
00489 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00490 void operator delete(void *ptr, const std::nothrow_t&) throw() { \
00491 Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); \
00492 } \
00493 typedef void eigen_aligned_operator_new_marker_type;
00494 #else
00495 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00496 #endif
00497
00498 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
00499 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
00500 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 template<class T>
00521 class aligned_allocator
00522 {
00523 public:
00524 typedef size_t size_type;
00525 typedef std::ptrdiff_t difference_type;
00526 typedef T* pointer;
00527 typedef const T* const_pointer;
00528 typedef T& reference;
00529 typedef const T& const_reference;
00530 typedef T value_type;
00531
00532 template<class U>
00533 struct rebind
00534 {
00535 typedef aligned_allocator<U> other;
00536 };
00537
00538 pointer address( reference value ) const
00539 {
00540 return &value;
00541 }
00542
00543 const_pointer address( const_reference value ) const
00544 {
00545 return &value;
00546 }
00547
00548 aligned_allocator() throw()
00549 {
00550 }
00551
00552 aligned_allocator( const aligned_allocator& ) throw()
00553 {
00554 }
00555
00556 template<class U>
00557 aligned_allocator( const aligned_allocator<U>& ) throw()
00558 {
00559 }
00560
00561 ~aligned_allocator() throw()
00562 {
00563 }
00564
00565 size_type max_size() const throw()
00566 {
00567 return std::numeric_limits<size_type>::max();
00568 }
00569
00570 pointer allocate( size_type num, const_pointer* hint = 0 )
00571 {
00572 static_cast<void>( hint );
00573 return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
00574 }
00575
00576 void construct( pointer p, const T& value )
00577 {
00578 ::new( p ) T( value );
00579 }
00580
00581 void destroy( pointer p )
00582 {
00583 p->~T();
00584 }
00585
00586 void deallocate( pointer p, size_type )
00587 {
00588 internal::aligned_free( p );
00589 }
00590
00591 bool operator!=(const aligned_allocator<T>& ) const
00592 { return false; }
00593
00594 bool operator==(const aligned_allocator<T>& ) const
00595 { return true; }
00596 };
00597
00598
00599
00600 #if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
00601 # if defined(__PIC__) && defined(__i386__)
00602
00603 # define EIGEN_CPUID(abcd,func,id) \
00604 __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
00605 # else
00606
00607 # define EIGEN_CPUID(abcd,func,id) \
00608 __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
00609 # endif
00610 #elif defined(_MSC_VER)
00611 # if (_MSC_VER > 1500) || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729)
00612 # define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id)
00613 # endif
00614 #endif
00615
00616 namespace internal {
00617
00618 #ifdef EIGEN_CPUID
00619
00620 inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
00621 {
00622 return abcd[1]==((int*)(vendor))[0] && abcd[3]==((int*)(vendor))[1] && abcd[2]==((int*)(vendor))[2];
00623 }
00624
00625 inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
00626 {
00627 int abcd[4];
00628 l1 = l2 = l3 = 0;
00629 int cache_id = 0;
00630 int cache_type = 0;
00631 do {
00632 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00633 EIGEN_CPUID(abcd,0x4,cache_id);
00634 cache_type = (abcd[0] & 0x0F) >> 0;
00635 if(cache_type==1||cache_type==3)
00636 {
00637 int cache_level = (abcd[0] & 0xE0) >> 5;
00638 int ways = (abcd[1] & 0xFFC00000) >> 22;
00639 int partitions = (abcd[1] & 0x003FF000) >> 12;
00640 int line_size = (abcd[1] & 0x00000FFF) >> 0;
00641 int sets = (abcd[2]);
00642
00643 int cache_size = (ways+1) * (partitions+1) * (line_size+1) * (sets+1);
00644
00645 switch(cache_level)
00646 {
00647 case 1: l1 = cache_size; break;
00648 case 2: l2 = cache_size; break;
00649 case 3: l3 = cache_size; break;
00650 default: break;
00651 }
00652 }
00653 cache_id++;
00654 } while(cache_type>0 && cache_id<16);
00655 }
00656
00657 inline void queryCacheSizes_intel_codes(int& l1, int& l2, int& l3)
00658 {
00659 int abcd[4];
00660 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00661 l1 = l2 = l3 = 0;
00662 EIGEN_CPUID(abcd,0x00000002,0);
00663 unsigned char * bytes = reinterpret_cast<unsigned char *>(abcd)+2;
00664 bool check_for_p2_core2 = false;
00665 for(int i=0; i<14; ++i)
00666 {
00667 switch(bytes[i])
00668 {
00669 case 0x0A: l1 = 8; break;
00670 case 0x0C: l1 = 16; break;
00671 case 0x0E: l1 = 24; break;
00672 case 0x10: l1 = 16; break;
00673 case 0x15: l1 = 16; break;
00674 case 0x2C: l1 = 32; break;
00675 case 0x30: l1 = 32; break;
00676 case 0x60: l1 = 16; break;
00677 case 0x66: l1 = 8; break;
00678 case 0x67: l1 = 16; break;
00679 case 0x68: l1 = 32; break;
00680 case 0x1A: l2 = 96; break;
00681 case 0x22: l3 = 512; break;
00682 case 0x23: l3 = 1024; break;
00683 case 0x25: l3 = 2048; break;
00684 case 0x29: l3 = 4096; break;
00685 case 0x39: l2 = 128; break;
00686 case 0x3A: l2 = 192; break;
00687 case 0x3B: l2 = 128; break;
00688 case 0x3C: l2 = 256; break;
00689 case 0x3D: l2 = 384; break;
00690 case 0x3E: l2 = 512; break;
00691 case 0x40: l2 = 0; break;
00692 case 0x41: l2 = 128; break;
00693 case 0x42: l2 = 256; break;
00694 case 0x43: l2 = 512; break;
00695 case 0x44: l2 = 1024; break;
00696 case 0x45: l2 = 2048; break;
00697 case 0x46: l3 = 4096; break;
00698 case 0x47: l3 = 8192; break;
00699 case 0x48: l2 = 3072; break;
00700 case 0x49: if(l2!=0) l3 = 4096; else {check_for_p2_core2=true; l3 = l2 = 4096;} break;
00701 case 0x4A: l3 = 6144; break;
00702 case 0x4B: l3 = 8192; break;
00703 case 0x4C: l3 = 12288; break;
00704 case 0x4D: l3 = 16384; break;
00705 case 0x4E: l2 = 6144; break;
00706 case 0x78: l2 = 1024; break;
00707 case 0x79: l2 = 128; break;
00708 case 0x7A: l2 = 256; break;
00709 case 0x7B: l2 = 512; break;
00710 case 0x7C: l2 = 1024; break;
00711 case 0x7D: l2 = 2048; break;
00712 case 0x7E: l2 = 256; break;
00713 case 0x7F: l2 = 512; break;
00714 case 0x80: l2 = 512; break;
00715 case 0x81: l2 = 128; break;
00716 case 0x82: l2 = 256; break;
00717 case 0x83: l2 = 512; break;
00718 case 0x84: l2 = 1024; break;
00719 case 0x85: l2 = 2048; break;
00720 case 0x86: l2 = 512; break;
00721 case 0x87: l2 = 1024; break;
00722 case 0x88: l3 = 2048; break;
00723 case 0x89: l3 = 4096; break;
00724 case 0x8A: l3 = 8192; break;
00725 case 0x8D: l3 = 3072; break;
00726
00727 default: break;
00728 }
00729 }
00730 if(check_for_p2_core2 && l2 == l3)
00731 l3 = 0;
00732 l1 *= 1024;
00733 l2 *= 1024;
00734 l3 *= 1024;
00735 }
00736
00737 inline void queryCacheSizes_intel(int& l1, int& l2, int& l3, int max_std_funcs)
00738 {
00739 if(max_std_funcs>=4)
00740 queryCacheSizes_intel_direct(l1,l2,l3);
00741 else
00742 queryCacheSizes_intel_codes(l1,l2,l3);
00743 }
00744
00745 inline void queryCacheSizes_amd(int& l1, int& l2, int& l3)
00746 {
00747 int abcd[4];
00748 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00749 EIGEN_CPUID(abcd,0x80000005,0);
00750 l1 = (abcd[2] >> 24) * 1024;
00751 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00752 EIGEN_CPUID(abcd,0x80000006,0);
00753 l2 = (abcd[2] >> 16) * 1024;
00754 l3 = ((abcd[3] & 0xFFFC000) >> 18) * 512 * 1024;
00755 }
00756 #endif
00757
00758
00759
00760 inline void queryCacheSizes(int& l1, int& l2, int& l3)
00761 {
00762 #ifdef EIGEN_CPUID
00763 int abcd[4];
00764
00765
00766 EIGEN_CPUID(abcd,0x0,0);
00767 int max_std_funcs = abcd[1];
00768 if(cpuid_is_vendor(abcd,"GenuineIntel"))
00769 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00770 else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
00771 queryCacheSizes_amd(l1,l2,l3);
00772 else
00773
00774 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 #else
00788 l1 = l2 = l3 = -1;
00789 #endif
00790 }
00791
00792
00793
00794 inline int queryL1CacheSize()
00795 {
00796 int l1(-1), l2, l3;
00797 queryCacheSizes(l1,l2,l3);
00798 return l1;
00799 }
00800
00801
00802
00803 inline int queryTopLevelCacheSize()
00804 {
00805 int l1, l2(-1), l3(-1);
00806 queryCacheSizes(l1,l2,l3);
00807 return std::max(l2,l3);
00808 }
00809
00810 }
00811
00812 #endif // EIGEN_MEMORY_H