2012-04-19 11 views
8

Bilgisayarımda 192GB RAM yüklü, 4GB üzerinde (donanım adresi 0x100000000'de) önyükleme sırasında Linux çekirdeği tarafından ayrılmış 188GB RAM var (mem = 4G memmap = 188 g $ 4G). Bir veri toplama çekirdeği modülü, DMA kullanılarak bir halka tamponu olarak kullanılan bu geniş alana veri biriktirir. Bir kullanıcı alanı uygulaması mmap bu halka arabelleğini kullanıcı boşluğuna yerleştirir, sonra hazır olduktan sonra işlemek için mevcut konumdaki halka arabelleği bloklarını kopyalar.Linux'taki mmap'ed fiziksel belleği için kullanıcı alanında yetersiz performans

Bu 16 MB'lık blokların memcpy kullanılarak mmap'ed alanından kopyalanması beklediğim gibi performans göstermiyor. Performansın, önyükleme zamanında ayrılmış olan belleğin boyutuna bağlı olduğu (ve daha sonra kullanıcı alanına mmap'ed) olduğu anlaşılmaktadır. (Kontrol çıkarılmış) esas olarak yapar

module_param(resmem_hwaddr, ulong, S_IRUSR); 
module_param(resmem_length, ulong, S_IRUSR); 
//... 
static int resmem_mmap(struct file *filp, struct vm_area_struct *vma) { 
remap_pfn_range(vma, vma->vm_start, 
    resmem_hwaddr >> PAGE_SHIFT, 
    resmem_length, vma->vm_page_prot); 
return 0; 
} 

ve bir test uygulaması,:

#define BLOCKSIZE ((size_t)16*1024*1024) 
int resMemFd = ::open(RESMEM_DEV, O_RDWR | O_SYNC); 
unsigned long resMemLength = 0; 
::ioctl(resMemFd, RESMEM_IOC_LENGTH, &resMemLength); 
void* resMemBase = ::mmap(0, resMemLength, PROT_READ | PROT_WRITE, MAP_SHARED, resMemFd, 4096); 
char* source = ((char*)resMemBase) + RESMEM_HEADER_SIZE;  
char* destination = new char[BLOCKSIZE]; 
struct timeval start, end; 
gettimeofday(&start, NULL); 
memcpy(destination, source, BLOCKSIZE); 
gettimeofday(&end, NULL); 
float time = (end.tv_sec - start.tv_sec)*1000.0f + (end.tv_usec - start.tv_usec)/1000.0f; 
    std::cout << "memcpy from mmap'ed to malloc'ed: " << time << "ms (" << BLOCKSIZE/1000.0f/time << "MB/s)" << std::endl; 

I taşıdı http://www.wurmsdobler.org/files/resmem.zip yapan bir çekirdek modülü için kaynak kodu mmap dosyası işlem uygular içerir

|  |   1GB   |   4GB   |   16GB   |  64GB   |  128GB   |   188GB 
|run 1 | 9.274ms (1809.06MB/s) | 11.503ms (1458.51MB/s) | 11.333ms (1480.39MB/s) | 9.326ms (1798.97MB/s) | 213.892ms ( 78.43MB/s) | 206.476ms ( 81.25MB/s) 
|run 2 | 4.255ms (3942.94MB/s) | 4.249ms (3948.51MB/s) | 4.257ms (3941.09MB/s) | 4.298ms (3903.49MB/s) | 208.269ms ( 80.55MB/s) | 200.627ms ( 83.62MB/s) 
012: bir SuperMicro 1026GT-tf-FM109 Ubuntu 10.04.4, Linux 2.6.32 ile ayrılmış RAM (resmem_length) farklı boyutları için bir 16MB veri bloğunun memcpy testler üzerindengözlemlerim şunlardır: malloc'ed için mmap ikinci vadede, memcpy İlk gelen

  1. içeriği zaten bir yere önbelleğe olabileceğini fayda görülmektedir.

  2. Hem 64 GB değerinde, hem de bir memcpy kullanırken dikkat edilmesi gereken önemli bir performans düşüşü var.

Bunun nedenini anlamak isterim. Belki Linux çekirdek geliştiricileri grup düşüncede birileri: 64GB (? Bu birşey hatırlatıyor mu)

Saygılarımızla peter kimse için yeterli olmalıdır

CPU muhtemelen onunla başa çıkmak için yeterli önbelleğe sahip olmayan

cevap

1

verimli. Düşük bellek kullanın ya da daha büyük bir önbellek ile bir CPU alın.

+0

Merhaba Ignacio, doğru olabilir. Bilgisayar iki adet Intel Xeon E5620 2 ile donatılmıştır.12MB L3 önbellek ve 1066MHz bellek hızı ile 4GHz dört çekirdekli. – PeterW

+0

Basit görünümüm, ilk okuma işlemi için RAM'deki içeriğin önbelleğe alınacağı ve miktarın önbellekte sığdığı sürece ikinci isteğin doğrudan önbellekten sunulacağıdır. Aktarılan veri miktarının memnum üzerinde bir etkisi olacağını düşünürdüm, benim durumumda <12MB, fakat takılı belleklerin toplam büyüklüğü değil, ya da RAM'de veri var. – PeterW

+0

Diğer testler, aynı performans düşüşünün daha küçük veri blokları için, ör. 1MB. Sadece önyükleme zamanında ayrılmış olan bellek miktarına bağlıyım, yani daha fazla değil 64GB. – PeterW

2

SuperMicro'nun geri bildirimlerine dayanarak, performans düşüşü, üniform olmayan bellek erişimi olan NUMA'ya bağlıdır. SuperMicro 1026GT-TF-FM109, X8DTG-DF anakartını, her biri 96GB RAM'e takılı iki Intel Xeon E5620 işlemcisine bağlı bir Intel 5520 Tylersburg yonga seti ile kullanıyor.

Uygulamamı CPU0 ile kilitlerseniz, hangi bellek alanının rezerve edildiğine ve dolayısıyla mmap'ed'e bağlı olarak farklı memcpy hızlarını gözlemleyebilirim. ayrılan bellek alanı dışı CPU ise, işini yapmak için bir süre mücadele mmap ve ve "uzak" alanından sonraki memcpy (veri bloğu boyutu = 16MB) daha uzun zaman almasına:

resmem=64G$4G (inside CPU0 realm): 3949MB/s 
resmem=64G$96G (outside CPU0 realm): 82MB/s 
resmem=64G$128G (outside CPU0 realm): 3948MB/s 
resmem=92G$4G (inside CPU0 realm): 3966MB/s    
resmem=92G$100G (outside CPU0 realm): 57MB/s 

Neredeyse mantıklı. Sadece üçüncü durumda, 64G $ 128, yani en yüksek 64GB, aynı zamanda iyi sonuçlar veriyor. Bu bir şekilde teori ile çelişir.

Selamlar, peter

+0

Her bir NUMA etki alanının RAM'inin 96 GiB'si varsa, "64g $ 128G" testi, ilk NUMA alanında yarısı ve ikinci NUMA alanında yarısı olacaktır. Son testin ("92G $ 100G") aşırı derecede tehlikeli olması muhtemeldir - firmware tipik olarak çeşitli şeyler için bir miktar RAM'i saklar ve üstte RAM, SMM eyaleti kaydedilen alanlar ve rastgele yazılımın kullanabileceği boş/kullanılabilir RAM gibi şeyler için kullanılabilir. çöp. – Brendan

İlgili konular