Secara terprogram mendapatkan ukuran garis cache?

177

Semua platform diterima, mohon tentukan platform untuk jawaban Anda.

Pertanyaan serupa: Bagaimana secara pemrograman mendapatkan ukuran halaman cache CPU dalam C ++?

paxos1977
sumber
8
FWIW, C ++ 17 akan memberikan perkiraan waktu kompilasi untuk hal ini: stackoverflow.com/questions/39680206/…
GManNickG
selain untuk C / C ++, jika Anda tidak keberatan menggunakan rakitan untuk mendapatkan info tersebut, Anda dapat melihatnya (memperluas info dari jawaban negamartin) pada kode sumber SDL_GetCPUCacheLineSizefungsi SDL2 , lalu lihat di cpuid macromana kode sumber rakitan untuk setiap model prosesor. Anda dapat melihatnya di imgur.com/a/KP57m6s , atau langsung mengintip sumbernya sendiri.
haxpor

Jawaban:

186

Di Linux (dengan kernel yang cukup baru), Anda bisa mendapatkan informasi ini dari / sys:

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

Direktori ini memiliki subdirektori untuk setiap level cache. Masing-masing direktori tersebut berisi file-file berikut:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Ini memberi Anda lebih banyak informasi tentang cache maka Anda akan berharap untuk tahu, termasuk ukuran cacheline ( coherency_line_size) serta apa CPU berbagi cache ini. Ini sangat berguna jika Anda melakukan pemrograman multithreaded dengan data bersama (Anda akan mendapatkan hasil yang lebih baik jika data berbagi thread juga berbagi cache).

spinfire
sumber
4
file mana yang berisi ukuran garis cache? Saya mengasumsikan coherency_line_size? atau partisi physical_line_?
paxos1977
27
coherency_line_size
spinfire
6
Yang pasti: ini dalam Bytes, ya?
Jakub M.
6
Ya, coherency_line_size dalam byte.
John Zwinck
4
@android: Saya menggunakan mesin fedora-18 x64 dengan prosesor core-i5. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizekembali 64di sistem saya. Sama untuk folder index1,2,3 juga.
Abid Rahman K
141

Di Linux lihat sysconf (3).

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Anda juga bisa mendapatkannya dari baris perintah menggunakan getconf:

$ getconf LEVEL1_DCACHE_LINESIZE
64
ob.
sumber
4
jawaban sederhana adalah yang terbaik!
FrankH.
3
@warunapww Ini dalam byte.
Maarten Bamelis
akhirnya! semoga lebih banyak orang melihat jawaban ini untuk menghemat waktu.
Elinx
118

Saya telah mengerjakan beberapa hal baris cache dan perlu menulis fungsi lintas platform. Saya berkomitmen untuk repo github di https://github.com/NickStrupat/CacheLineSize , atau Anda bisa menggunakan sumber di bawah ini. Jangan ragu untuk melakukan apa pun yang Anda inginkan dengannya.

#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
Nick Strupat
sumber
15
Mungkin lebih baik menggunakan sysconf (_SC_LEVEL1_DCACHE_LINESIZE) untuk linux.
Matt
@ Mat mengapa? Hanya penasaran :-).
user35915
31

Pada x86, Anda dapat menggunakan instruksi CPUID dengan fungsi 2 untuk menentukan berbagai properti cache dan TLB. Mem-parsing keluaran fungsi 2 agak rumit, jadi saya akan merujuk Anda ke bagian 3.1.3 dari Intel Processor Identification dan CPUID Instruction (PDF).

Untuk mendapatkan data ini dari kode C / C ++, Anda harus menggunakan perakitan inline, kompiler intrinsik, atau memanggil fungsi perakitan eksternal untuk melakukan instruksi CPUID.

Adam Rosenfield
sumber
ada yang tahu tentang cara melakukan ini dengan prosesor lain dengan built in cache?
paxos1977
3
@ceretullis: Errr ... x86 sudah ada di dalam cache. Apa "prosesor lain" yang Anda cari? Apa yang Anda minta bergantung pada platform.
Billy ONeal
9

Jika Anda menggunakan SDL2, Anda dapat menggunakan fungsi ini:

int SDL_GetCPUCacheLineSize(void);

Yang mengembalikan ukuran ukuran garis cache L1, dalam byte.

Di mesin x86_64 saya, jalankan snippet kode ini:

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

Menghasilkan CacheLineSize = 64

Saya tahu saya sedikit terlambat, tetapi hanya menambahkan informasi untuk pengunjung masa depan. Dokumentasi SDL saat ini mengatakan nomor yang dikembalikan adalah dalam KB, tetapi sebenarnya dalam byte.

negamartin
sumber
Ya ampun ini sangat membantu. Saya akan menulis beberapa permainan di SDL2 jadi ini akan sangat berguna
Nicholas Humphrey
7

Pada platform Windows:

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

Fungsi GetLogicalProcessorInformation akan memberi Anda karakteristik prosesor logis yang digunakan oleh sistem. Anda dapat menjalankan SYSTEM_LOGICAL_PROCESSOR_INFORMATION yang dikembalikan oleh fungsi mencari entri tipe RelationCache. Setiap entri tersebut berisi ProcessorMask yang memberi tahu Anda prosesor mana yang digunakan untuk entri, dan dalam CACHE_DESCRIPTOR, ia memberi tahu Anda jenis cache apa yang sedang dijelaskan dan seberapa besar garis cache untuk cache itu.

Lorenzo Boccaccia
sumber
4

ARMv6 dan di atasnya memiliki C0atau Tipe Cache Register. Namun, ini hanya tersedia dalam mode istimewa.

Misalnya, dari Manual Referensi Teknis Cortex ™ -A8 :

Tujuan dari Cache Type Register adalah untuk menentukan instruksi dan cache data panjang minimum garis dalam byte untuk memungkinkan berbagai alamat menjadi tidak valid.

Register Jenis Cache adalah:

  • register read-only
  • hanya dapat diakses dalam mode istimewa.

Isi Daftar Tipe Cache tergantung pada implementasi spesifik. Gambar 3-2 menunjukkan pengaturan bit dari Cache Type Register ...


Jangan menganggap prosesor ARM memiliki cache (tampaknya, beberapa dapat dikonfigurasi tanpa satu). Cara standar untuk menentukannya adalah melalui C0. Dari ARM ARM , halaman B6-6:

Dari ARMv6, register Tipe Kontrol Sistem Coprocessor Cache adalah metode yang diamanatkan untuk mendefinisikan cache L1, lihat register Tipe Cache pada halaman B6-14. Ini juga merupakan metode yang direkomendasikan untuk varian arsitektur sebelumnya. Selain itu, Pertimbangan untuk level cache tambahan pada halaman B6-12 menjelaskan pedoman arsitektur untuk dukungan cache level 2.

jww
sumber
3

Anda juga dapat mencoba melakukannya secara terprogram dengan mengukur waktu. Jelas, itu tidak akan selalu setepat cpuid dan sejenisnya, tetapi lebih portabel. ATLAS melakukannya pada tahap konfigurasinya, Anda mungkin ingin melihatnya:

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

David Cournapeau
sumber