2012-04-19 24 views
8

Trong số 192GB RAM được cài đặt trên máy tính của tôi, tôi có RAM 188GB trên 4GB (tại địa chỉ phần cứng 0x100000000) do hạt nhân Linux cài đặt lúc khởi động (mem = 4G memmap = 188G $ 4G). Mô-đun hạt nhân thu thập dữ liệu tích lũy dữ liệu vào khu vực rộng lớn này được sử dụng làm bộ đệm vòng sử dụng DMA. Một bộ đệm vòng đệm của ứng dụng không gian người dùng này mmap vào vùng người dùng, sau đó sao chép các khối từ bộ đệm vòng tại vị trí hiện tại để xử lý khi chúng đã sẵn sàng.Hiệu năng memcpy kém trong không gian người dùng cho bộ nhớ vật lý mmap'ed trong Linux

Sao chép các khối 16MB này từ khu vực mmap'ed bằng memcpy không hoạt động như tôi mong đợi. Dường như hiệu suất phụ thuộc vào kích thước của bộ nhớ được đặt trước thời gian khởi động (và sau đó được chuyển vào không gian người dùng). http://www.wurmsdobler.org/files/resmem.zip chứa mã nguồn cho một mô-đun hạt nhân mà không thực hiện các thao tác trên file mmap:

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; 
} 

và một ứng dụng thử nghiệm, mà hiện trong bản chất (với kiểm tra loại bỏ):

#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; 

tôi đã tiến hành thử nghiệm memcpy của một khối dữ liệu 16MB cho các kích thước khác nhau của RAM dành riêng (resmem_length) trên Ubuntu 10.04.4, Linux 2.6.32, trên SuperMicro 1026GT-TF-FM109:

|  |   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) 

quan sát của tôi là:

  1. Từ người đầu tiên chạy thứ hai, memcpy từ mmap'ed để malloc'ed dường như được hưởng lợi mà các nội dung đã có thể được lưu trữ ở đâu đó.

  2. Có sự sụt giảm hiệu suất đáng kể từ> 64GB, có thể nhận thấy cả khi sử dụng memcpy.

Tôi muốn hiểu tại sao lại như vậy. Có lẽ ai đó trong các nhà phát triển hạt nhân nhóm suy nghĩ Linux: 64GB nên là đủ cho bất cứ ai (không nhẫn này một cái chuông?)

Trân trọng! peter

Trả lời

1

CPU của bạn có thể không có đủ bộ nhớ cache để đối phó với nó hiệu quả. Hoặc sử dụng bộ nhớ thấp hơn, hoặc có được một CPU với một bộ nhớ cache lớn hơn.

+0

Xin chào Ignacio, bạn có thể đúng. Máy tính được trang bị hai Intel Xeon E5620 2.Lõi tứ 4GHz với bộ nhớ cache L3 12MB và tốc độ bộ nhớ 1066MHz. – PeterW

+0

Quan điểm đơn giản của tôi là đối với hoạt động đọc đầu tiên, nội dung trong RAM sẽ được lưu vào bộ nhớ cache và yêu cầu thứ hai sẽ được phân phát trực tiếp từ bộ nhớ cache, miễn là số tiền phù hợp với bộ nhớ cache. Tôi đã có thể nghĩ rằng số lượng dữ liệu được chuyển sẽ có tác dụng trên memcpy, trong trường hợp của tôi <12MB, nhưng không phải là tổng dung lượng bộ nhớ được lắp đặt hoặc trong RAM của dữ liệu. – PeterW

+0

Các thử nghiệm khác đã cho thấy rằng sự suy giảm hiệu suất giống nhau cho thấy các khối dữ liệu nhỏ hơn, ví dụ: 1MB. Tôi chỉ dường như phụ thuộc vào lượng bộ nhớ được đặt trước thời gian khởi động, tức là không nhiều hơn 64GB. – PeterW

2

Dựa trên phản hồi từ SuperMicro, sự xuống cấp hiệu suất là do NUMA, truy cập bộ nhớ không đồng bộ. SuperMicro 1026GT-TF-FM109 sử dụng bo mạch chủ X8DTG-DF với một chipset Intel 5520 Tylersburg ở trung tâm, được kết nối với hai CPU Intel Xeon E5620, mỗi bộ có kèm theo RAM 96GB.

Nếu tôi khóa ứng dụng của mình vào CPU0, tôi có thể quan sát các tốc độ ghi nhớ khác nhau tùy thuộc vào vùng bộ nhớ đã được đặt trước và do đó được tạo ra. Nếu khu vực bộ nhớ dành riêng là off-CPU, sau đó mmap cuộc đấu tranh cho một số thời gian để làm công việc của mình, và bất kỳ tiếp theo memcpy đến và đi từ khu vực "từ xa" tiêu thụ nhiều thời gian (dữ liệu khối size = 16MB):

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 

Nó gần như có ý nghĩa. Chỉ có trường hợp thứ ba, 64G $ 128, có nghĩa là 64GB trên cùng cũng mang lại kết quả tốt. Điều này mâu thuẫn với lý thuyết nào đó.

Trân trọng, peter

+0

Nếu mỗi miền NUMA có 96 GiB RAM thì thử nghiệm "64g $ 128G" sẽ là một nửa trong tên miền NUMA đầu tiên và một nửa trong miền NUMA thứ hai. Bài kiểm tra cuối cùng ("92G $ 100G") có khả năng gây nguy hiểm quá mức - phần cứng thường chứa một số RAM cho nhiều thứ và RAM ở đầu có thể được sử dụng cho những thứ như SMM tiết kiệm và không sử dụng RAM miễn phí/phần mềm ngẫu nhiên rác. – Brendan

Các vấn đề liên quan