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à:
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 đó.
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
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
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
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