Programlı olarak önbellek satır boyutunu al?


177

Tüm platformlar hoş geldiniz, lütfen cevabınız için platformu belirtin.

Benzer bir soru: Programlı olarak C ++ 'da CPU önbellek sayfası boyutu nasıl alınır?


8
FWIW, C ++ 17 bunun derleme zamanı yaklaşımını sağlayacaktır: stackoverflow.com/questions/39680206/…
GManNickG

C / C ++ için bir kenara, bu tür bilgileri almak için derleme kullanmayı düşünmezseniz, SDL2'nin kaynak SDL_GetCPUCacheLineSizeişlev koduna bir göz atabilir (negamartin'in cevabından bilgi genişleterek) , ardından cpuid macroher biri için derleme kaynak koduna sahip bir göz atabilirsiniz işlemci modeli. İmgur.com/ a/ KP57m6s adresine bakabilir veya doğrudan kaynağa bakabilirsiniz .
haxpor

Yanıtlar:


186

Linux'ta (oldukça yeni bir çekirdeğe sahip), bu bilgileri / sys'den alabilirsiniz:

/sys/devices/system/cpu/cpu0/cache/

Bu dizinin her önbellek düzeyi için bir alt dizini vardır. Bu dizinlerin her biri aşağıdaki dosyaları içerir:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Bu size önbellek hakkında daha fazla bilgi verir, o zaman önbellek boyutu ( coherency_line_size) ve CPU'ların bu önbelleği paylaştığı özellikler de dahil olmak üzere umarız . Paylaşılan verilerle çok iş parçacıklı programlama yapıyorsanız bu çok kullanışlıdır (verileri paylaşan iş parçacıkları da bir önbellek paylaşıyorsa daha iyi sonuçlar alırsınız).


4
dosyalardan hangileri önbellek satır boyutunu içerir? Ben coherency_line_size varsayıyorum? ya da physical_line_partition?
paxos1977

27
coherency_line_size
spinfire

6
Emin olmak için: bu Bayt'ta, değil mi?
Jakub M.29

6
Evet, coherency_line_size bayt cinsindendir.
John Zwinck

4
@android: Core-i5 işlemcili fedora-18 x64 makinesi kullanıyorum. sistemime cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizegeri döner 64. İndex1,2,3 klasörleri için de aynıdır.
Abid Rahman K

141

Linux'ta sysconf (3) 'e bakın.

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Bunu getconf komutunu kullanarak komut satırından da alabilirsiniz:

$ getconf LEVEL1_DCACHE_LINESIZE
64

4
basit cevaplar sadece en iyisidir!
FrankH.

3
@warunapww Bayt cinsindendir.
Maarten Bamelis

en sonunda! Umarım daha fazla adam zaman kazanmak için bu cevabı görür.
elinx

118

Bazı önbellek satırları üzerinde çalışıyorum ve platformlar arası bir işlev yazmam gerekiyordu. Bunu https://github.com/NickStrupat/CacheLineSize adresinden bir github repo'ya adadım , ya da sadece aşağıdaki kaynağı kullanabilirsiniz. Onunla ne istersen yapmaktan çekinmeyin.

#ifndef GET_CACHE_LINE_SIZE_H_INCLUDED
#define GET_CACHE_LINE_SIZE_H_INCLUDED

// Author: Nick Strupat
// Date: October 29, 2010
// Returns the cache line size (in bytes) of the processor, or 0 on failure

#include <stddef.h>
size_t cache_line_size();

#if defined(__APPLE__)

#include <sys/sysctl.h>
size_t cache_line_size() {
    size_t line_size = 0;
    size_t sizeof_line_size = sizeof(line_size);
    sysctlbyname("hw.cachelinesize", &line_size, &sizeof_line_size, 0, 0);
    return line_size;
}

#elif defined(_WIN32)

#include <stdlib.h>
#include <windows.h>
size_t cache_line_size() {
    size_t line_size = 0;
    DWORD buffer_size = 0;
    DWORD i = 0;
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0;

    GetLogicalProcessorInformation(0, &buffer_size);
    buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(buffer_size);
    GetLogicalProcessorInformation(&buffer[0], &buffer_size);

    for (i = 0; i != buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
        if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) {
            line_size = buffer[i].Cache.LineSize;
            break;
        }
    }

    free(buffer);
    return line_size;
}

#elif defined(linux)

#include <stdio.h>
size_t cache_line_size() {
    FILE * p = 0;
    p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
    unsigned int i = 0;
    if (p) {
        fscanf(p, "%d", &i);
        fclose(p);
    }
    return i;
}

#else
#error Unrecognized platform
#endif

#endif

15
Linux için sysconf (_SC_LEVEL1_DCACHE_LINESIZE) kullanmak daha iyi olabilir.
Matt

@Matt neden? Sadece merak :-).
user35915

31

X86'da , önbellek ve TLB'nin çeşitli özelliklerini belirlemek için işlev 2 ile CPUID komutunu kullanabilirsiniz . İşlev 2'nin çıktısını ayrıştırmak biraz karmaşıktır, bu yüzden sizi Intel İşlemci Tanımlaması ve CPUID Talimatı'nın (PDF) 3.1.3 bölümüne yönlendireceğim .

Bu verileri C / C ++ kodundan almak için satır içi montaj, derleyici içsel kullanmanız veya CPUID komutunu gerçekleştirmek için harici bir montaj işlevi çağırmanız gerekir.


kimse bunu dahili önbellek ile diğer işlemciler ile nasıl biliyor?
paxos1977

3
@ceretullis: Errr ... x86 önbellekte oluşturuldu. Özellikle hangi "diğer işlemciler" i arıyorsunuz? İstediğiniz şey platforma bağlıdır.
Billy ONeal

9

SDL2 kullanıyorsanız bu işlevi kullanabilirsiniz:

int SDL_GetCPUCacheLineSize(void);

Bu, bayt cinsinden L1 önbellek satır boyutunun boyutunu döndürür.

X86_64 makinemde bu kod snippet'ini çalıştırma:

printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());

üretir CacheLineSize = 64

Biraz geç kaldığımı biliyorum, ama sadece gelecekteki ziyaretçiler için bilgi ekliyorum. SDL belgeleri şu anda döndürülen sayının KB cinsinden olduğunu, ancak aslında bayt cinsinden olduğunu söylüyor.


Ah bu gerçekten çok yardımcı. SDL2'de bir oyun yazacağım, bu gerçekten yararlı olacak
Nicholas Humphrey

7

Windows platformunda:

dan http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx

GetLogicalProcessorInformation işlevi size sistem tarafından kullanılan mantıksal işlemcilerin özelliklerini verecektir. RelationCache türünde girdileri arayan işlev tarafından döndürülen SYSTEM_LOGICAL_PROCESSOR_INFORMATION yürüyebilirsiniz. Bu girişlerin her biri, girişin hangi işlemci (ler) için geçerli olduğunu söyleyen bir ProcessorMask içerir ve CACHE_DESCRIPTOR'da, hangi önbellek türünün tanımlandığını ve önbellek satırının o önbellek için ne kadar büyük olduğunu söyler.


4

ARMv6 ve üzeri C0veya Önbellek Türü Kaydı vardır. Ancak, yalnızca ayrıcalıklı modda kullanılabilir.

Örneğin, Cortex ™ -A8 Teknik Referans Kılavuzu'ndan :

Önbellek Türü Kaydının amacı, bir dizi adresin geçersiz kılınmasını sağlamak için bayt cinsinden talimat ve veri önbelleği minimum satır uzunluğunu belirlemektir.

Önbellek Türü Kaydı:

  • salt okunur bir kayıt
  • yalnızca ayrıcalıklı modlarda erişilebilir.

Önbellek Türü Kaydının içeriği belirli uygulamaya bağlıdır. Şekil 3-2, Önbellek Türü Kaydının bit düzenlemesini göstermektedir ...


ARM işlemcinin bir önbelleği olduğunu varsaymayın (görünüşe göre, bazıları bir tane olmadan yapılandırılabilir). Bunu belirlemenin standart yolu C0. Gönderen ARM ARM , sayfa B6-6:

ARMv6'dan, Sistem Kontrol Yardımcı İşlemcisi Önbellek Tipi kaydı L1 önbelleklerini tanımlamak için zorunlu yöntemdir, bkz. Önbellek Türü kaydı sayfa B6-14. Ayrıca mimarinin önceki varyantları için önerilen yöntemdir. Ayrıca, ek önbellek düzeyleri için dikkat edilmesi gereken noktalar sayfa B6-12, düzey 2 önbellek desteği için mimari yönergeleri açıklar.


3

Bazı zamanlamaları ölçerek programlı olarak da deneyebilirsiniz. Açıkçası, her zaman cpuid ve benzerleri kadar kesin olmayacak, ancak daha taşınabilir. ATLAS bunu yapılandırma aşamasında yapar, bakmak isteyebilirsiniz:

http://math-atlas.sourceforge.net/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.