Googling và ack
-ing đã kết thúc! Tôi đã có một số câu trả lời.
Nhưng trước hết hãy để tôi làm rõ mục tiêu của câu hỏi thêm một chút: tôi muốn phân biệt rõ ràng các quy trình độc lập trong hệ thống và bộ đếm hiệu suất của chúng. Chẳng hạn, lõi của bộ xử lý, thiết bị uncore (đã tìm hiểu về nó gần đây), kernel hoặc ứng dụng người dùng trên bộ xử lý, bus (= bộ điều khiển bus), ổ cứng đều là các tiến trình độc lập, chúng không được đồng bộ hóa bởi đồng hồ . Và ngày nay có lẽ tất cả chúng đều có một số Bộ đếm giám sát quá trình (PMC). Tôi muốn hiểu quy trình mà các quầy đến từ đâu. (Nó cũng hữu ích trong việc googling: "nhà cung cấp" của một thứ không tốt hơn.)
Ngoài ra, thiết bị được sử dụng cho tìm kiếm: Ubuntu 14.04
,, linux 3.13.0-103-generic
bộ xử lý Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
(từ /proc/cpuinfo
, nó có 2 lõi vật lý và 4 ảo - vật chất ở đây).
Thuật ngữ, những điều câu hỏi liên quan
Từ Intel:
bộ xử lý là một core
thiết bị (đó là 1 thiết bị / quy trình) và một loạt các uncore
thiết bị , core
là những gì chạy chương trình (đồng hồ, ALU, thanh ghi, v.v.), uncore
là các thiết bị được đặt chết, gần với bộ xử lý vì tốc độ và độ trễ thấp (lý do thực sự là "bởi vì nhà sản xuất có thể làm được"); theo tôi hiểu thì về cơ bản nó là Northbridge, giống như trên bo mạch chủ PC, cộng với bộ nhớ cache; và AMD thực sự gọi các thiết bị này là NorthBridge instead of
uncore`;
ubox
mà xuất hiện trong tôi sysfs
$ find /sys/devices/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
- là một uncore
thiết bị, quản lý Cache cấp độ cuối (LLC, thiết bị cuối cùng trước khi nhấn RAM); Tôi có 2 lõi, do đó 2 LLC và 2 ubox
;
Bộ giám sát bộ xử lý (PMU) là một thiết bị riêng biệt theo dõi hoạt động của bộ xử lý và ghi lại chúng trong Bộ đếm giám sát bộ xử lý (PMC) (đếm lỗi bộ nhớ cache, chu kỳ bộ xử lý, v.v.); chúng tồn tại trên core
và uncore
các thiết bị; những core
cái được truy cập với rdpmc
hướng dẫn (đọc PMC); các uncore
, vì những thiết bị này phụ thuộc vào bộ xử lý thực tế trong tầm tay, được truy cập thông qua thanh ghi cụ Model (MSR) qua rdmsr
(tự nhiên);
rõ ràng, quy trình làm việc với chúng được thực hiện thông qua các cặp thanh ghi - 1 thanh ghi đặt các sự kiện mà bộ đếm đếm, 2 thanh ghi là giá trị trong bộ đếm; bộ đếm có thể được cấu hình để tăng sau một loạt các sự kiện, không chỉ 1; + có một số interupts / công nghệ thông báo tràn trong các quầy này;
nhiều người có thể tìm thấy trong "Hướng dẫn dành cho nhà phát triển phần mềm IA-32 Vol 3B" của Intel chương 18 "THEO D MONI THỰC HIỆN";
Ngoài ra, định dạng của MSR cụ thể cho các uncore
PMC này cho phiên bản "Giám sát hiệu suất kiến trúc phiên bản 1" (có các phiên bản 1-4 trong hướng dẫn, tôi không biết bộ xử lý nào của tôi) được mô tả trong "Hình 18-1. của IA32_PERFEVTSELx MSRs (trang 18-3 của tôi) và phần "18.2.1.2 Các sự kiện biểu diễn kiến trúc được xác định trước" với "Bảng 18-1. UMask và Sự kiện Chọn mã hóa cho các sự kiện biểu diễn kiến trúc được xác định trước", cho thấy các sự kiện hiển thị như Hardware event
trong perf list
.
Từ nhân linux:
kernel có một hệ thống (trừu tượng / lớp) để quản lý các bộ đếm hiệu suất có nguồn gốc khác nhau, cả phần mềm (kernel) và phần cứng, nó được mô tả trong linux-source-3.13.0/tools/perf/design.txt
; một sự kiện trong hệ thống này được định nghĩa là struct perf_event_attr
(tệp linux-source-3.13.0/include/uapi/linux/perf_event.h
), phần chính của __u64 config
trường có lẽ là trường - nó có thể chứa cả định nghĩa sự kiện dành riêng cho CPU (từ 64 bit theo định dạng được mô tả trên các số liệu của Intel) hoặc sự kiện của hạt nhân
MSB của từ cấu hình biểu thị nếu phần còn lại chứa [sự kiện của CPU thô hoặc kernel]
sự kiện của kernel được xác định với 7 bit cho loại và 56 cho mã định danh của sự kiện, là enum
-s trong mã, trong trường hợp của tôi là:
$ ak PERF_TYPE linux-source-3.13.0/include/
...
linux-source-3.13.0/include/uapi/linux/perf_event.h
29: PERF_TYPE_HARDWARE = 0,
30: PERF_TYPE_SOFTWARE = 1,
31: PERF_TYPE_TRACEPOINT = 2,
32: PERF_TYPE_HW_CACHE = 3,
33: PERF_TYPE_RAW = 4,
34: PERF_TYPE_BREAKPOINT = 5,
36: PERF_TYPE_MAX, /* non-ABI */
( ak
là bí danh của tôi ack-grep
, là tên của ack
Debian; và ack
thật tuyệt vời);
trong mã nguồn của kernel, người ta có thể thấy các hoạt động như "đăng ký tất cả các PMU được phát hiện trên hệ thống" và các kiểu cấu trúc struct pmu
, được chuyển đến một cái gì đó giống như int perf_pmu_register(struct pmu *pmu, const char *name, int type)
- do đó, người ta có thể gọi hệ thống này là "PMU của kernel", đó sẽ là một tập hợp của tất cả các PMU trên hệ thống; nhưng tên này có thể được hiểu là hệ thống giám sát các hoạt động của kernel, sẽ gây hiểu nhầm;
Hãy gọi hệ thống con này perf_events
cho rõ ràng;
như bất kỳ hệ thống con kernel nào, hệ thống con này có thể được xuất sang sysfs
(được tạo ra để xuất các hệ thống con kernel để mọi người sử dụng); và đó là những events
thư mục nào trong hệ thống con của tôi /sys/
- xuất khẩu (một phần của?) perf_events
;
Ngoài ra, tiện ích không gian người dùng perf
(được tích hợp trong linux) vẫn là một chương trình riêng biệt và có sự trừu tượng riêng; nó đại diện cho một sự kiện được người dùng yêu cầu giám sát dưới dạng perf_evsel
(tệp linux-source-3.13.0/tools/perf/util/evsel.{h,c}
) - cấu trúc này có một trường struct perf_event_attr attr;
, nhưng cũng là một trường giống như struct cpu_map *cpus;
cách perf
tiện ích gán một sự kiện cho tất cả hoặc các CPU cụ thể.
Câu trả lời
Thật vậy, Hardware cache event
là "lối tắt" cho các sự kiện của thiết bị bộ đệm ( ubox
của uncore
thiết bị Intel ), dành riêng cho bộ xử lý và có thể được truy cập qua giao thức Raw hardware event descriptor
. Và Hardware event
ổn định hơn trong kiến trúc, theo tôi hiểu, đặt tên cho các sự kiện từ core
thiết bị. Không có "phím tắt" nào trong kernel của tôi 3.13
tới một số uncore
sự kiện và bộ đếm khác. Tất cả phần còn lại - Software
và Tracepoints
- là các sự kiện của kernel.
Tôi tự hỏi nếu core
's Hardware event
s được truy cập thông qua cùng một Raw hardware event descriptor
giao thức. Họ có thể không - vì bộ đếm / PMU nằm trên core
, có thể nó được truy cập khác nhau. Ví dụ, với rdpmu
hướng dẫn đó , thay vì rdmsr
, truy cập uncore
. Nhưng nó không quan trọng.
Kernel PMU event
chỉ là các sự kiện, được xuất khẩu vào sysfs
. Tôi không biết làm thế nào được thực hiện (tự động bởi kernel tất cả các PMC được phát hiện trên hệ thống, hoặc chỉ một cái gì đó được mã hóa cứng và nếu tôi thêm một kprobe
- nó có được xuất không? V.v.). Nhưng điểm chính là đây là những sự kiện tương tự Hardware event
hoặc bất kỳ sự kiện nào khác trong perf_event
hệ thống nội bộ .
Và tôi không biết những gì
$ ls /sys/devices/uncore_cbox_0/events
clockticks
Chúng tôi.
Chi tiết về Kernel PMU event
Tìm kiếm thông qua mã dẫn đến:
$ ak "Kernel PMU" linux-source-3.13.0/tools/perf/
linux-source-3.13.0/tools/perf/util/pmu.c
629: printf(" %-50s [Kernel PMU event]\n", aliases[j]);
- xảy ra trong hàm
void print_pmu_events(const char *event_glob, bool name_only) {
...
while ((pmu = perf_pmu__scan(pmu)) != NULL)
list_for_each_entry(alias, &pmu->aliases, list) {...}
...
/* b.t.w. list_for_each_entry is an iterator
* apparently, it takes a block of {code} and runs over some lost
* Ruby built in kernel!
*/
// then there is a loop over these aliases and
loop{ ... printf(" %-50s [Kernel PMU event]\n", aliases[j]); ... }
}
và perf_pmu__scan
nằm trong cùng một tệp:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
...
pmu_read_sysfs(); // that's what it calls
}
- cũng nằm trong cùng một tệp:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
Đó là nó.
Chi tiết về Hardware event
vàHardware cache event
Rõ ràng, Hardware event
xuất phát từ cái mà Intel gọi là "Sự kiện hiệu suất kiến trúc được xác định trước", 18.2.1.2 trong Hướng dẫn dành cho nhà phát triển phần mềm IA-32 Vol 3B. Và "TỔNG QUAN GIÁM SÁT GIÁM SÁT 18.1" của tài liệu hướng dẫn mô tả chúng như sau:
Lớp thứ hai của khả năng giám sát hiệu suất được gọi là giám sát hiệu suất kiến trúc. Lớp này hỗ trợ các cách sử dụng lấy mẫu sự kiện dựa trên đếm và gián đoạn tương tự, với một tập hợp nhỏ hơn các sự kiện có sẵn. Hành vi có thể nhìn thấy của các sự kiện hiệu suất kiến trúc là nhất quán trong quá trình triển khai bộ xử lý. Tính khả dụng của khả năng giám sát hiệu suất kiến trúc được liệt kê bằng CPUID.0AH. Những sự kiện này được thảo luận trong Phần 18.2.
- loại khác là:
Bắt đầu với bộ xử lý Intel Core Solo và Intel Core Duo, có hai loại khả năng giám sát hiệu suất. Lớp đầu tiên hỗ trợ các sự kiện để theo dõi hiệu suất bằng cách sử dụng tính năng lấy mẫu sự kiện dựa trên đếm hoặc gián đoạn. Những sự kiện này không mang tính kiến trúc và thay đổi từ mô hình bộ xử lý này sang mô hình khác ...
Và những sự kiện này thực sự chỉ là liên kết đến các sự kiện phần cứng "thô" tiềm ẩn, có thể được truy cập thông qua perf
tiện ích như Raw hardware event descriptor
.
Để kiểm tra cái này nhìn vào linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
:
/*
* Intel PerfMon, used on Core and later.
*/
static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
{
[PERF_COUNT_HW_CPU_CYCLES] = 0x003c,
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e,
[PERF_COUNT_HW_CACHE_MISSES] = 0x412e,
...
}
- và chính xác 0x412e
được tìm thấy trong "Bảng 18-1. UMask và Sự kiện Chọn mã hóa cho các sự kiện hiệu suất kiến trúc được xác định trước" cho "Misses LLC":
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
- H
là cho hex. Tất cả 7 là trong cấu trúc, cộng [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *
. (Cách đặt tên hơi khác một chút, địa chỉ giống nhau.)
Sau đó, Hardware cache event
s nằm trong các cấu trúc như (trong cùng một tệp):
static __initconst const u64 snb_hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
{...}
- cái nào nên dùng cho cầu cát?
Một trong số này - snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]
chứa đầy SNB_DMND_WRITE|SNB_L3_ACCESS
, trong đó từ def-s ở trên:
#define SNB_L3_ACCESS SNB_RESP_ANY
#define SNB_RESP_ANY (1ULL << 16)
#define SNB_DMND_WRITE (SNB_DMND_RFO|SNB_LLC_RFO)
#define SNB_DMND_RFO (1ULL << 1)
#define SNB_LLC_RFO (1ULL << 8)
cái nào cũng bằng 0x00010102
, nhưng tôi không biết cách kiểm tra nó với một số bảng.
Và điều này cho một ý tưởng về cách nó được sử dụng trong perf_events
:
$ ak hw_cache_extra_regs linux-source-3.13.0/arch/x86/kernel/cpu/
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.c
50:u64 __read_mostly hw_cache_extra_regs
292: attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.h
521:extern u64 __read_mostly hw_cache_extra_regs
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
272:static __initconst const u64 snb_hw_cache_extra_regs
567:static __initconst const u64 nehalem_hw_cache_extra_regs
915:static __initconst const u64 slm_hw_cache_extra_regs
2364: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2365: sizeof(hw_cache_extra_regs));
2407: memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
2408: sizeof(hw_cache_extra_regs));
2424: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2425: sizeof(hw_cache_extra_regs));
2452: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2453: sizeof(hw_cache_extra_regs));
2483: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2484: sizeof(hw_cache_extra_regs));
2516: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
$
Các memcpy
s được thực hiện trong __init int intel_pmu_init(void) {... case:...}
.
Chỉ attr->config1
là một chút kỳ lạ. Nhưng nó ở đó, trong perf_event_attr
(cùng một linux-source-3.13.0/include/uapi/linux/perf_event.h
tệp):
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
Chúng được đăng ký trong perf_events
hệ thống của kernel với các lệnh gọi đến int perf_pmu_register(struct pmu *pmu, const char *name, int type)
(được xác định trong linux-source-3.13.0/kernel/events/core.c:
):
static int __init init_hw_perf_events(void)
(tập tin arch/x86/kernel/cpu/perf_event.c
) với cuộc gọiperf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
(tập tin arch/x86/kernel/cpu/perf_event_intel_uncore.c
, cũng có arch/x86/kernel/cpu/perf_event_amd_uncore.c
) với cuộc gọiret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
Vì vậy, cuối cùng, tất cả các sự kiện đến từ phần cứng và mọi thứ đều ổn. Nhưng ở đây người ta có thể nhận thấy: tại sao chúng ta có LLC-loads
trong perf list
và không ubox1 LLC-loads
, vì đây là những sự kiện HW và họ actualy đến từ ubox
es?
Đó là một điều perf
tiện ích và perf_evsel
cấu trúc của nó : khi bạn yêu cầu một sự kiện CTNH từ perf
bạn xác định sự kiện mà bộ xử lý bạn muốn nó (mặc định là tất cả), và nó thiết lập perf_evsel
với sự kiện và bộ xử lý được yêu cầu, sau đó tổng hợp là tính tổng các bộ đếm từ tất cả các bộ xử lý trong perf_evsel
(hoặc thực hiện một số thống kê khác với chúng).
Người ta có thể thấy nó trong tools/perf/builtin-stat.c
:
/*
* Read out the results of a single counter:
* aggregate counts across CPUs in system-wide mode
*/
static int read_counter_aggr(struct perf_evsel *counter)
{
struct perf_stat *ps = counter->priv;
u64 *count = counter->counts->aggr.values;
int i;
if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
thread_map__nr(evsel_list->threads), scale) < 0)
return -1;
for (i = 0; i < 3; i++)
update_stats(&ps->res_stats[i], count[i]);
if (verbose) {
fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
perf_evsel__name(counter), count[0], count[1], count[2]);
}
/*
* Save the full runtime - to allow normalization during printout:
*/
update_shadow_stats(counter, count);
return 0;
}
(Vì vậy, đối với tiện ích, perf
"bộ đếm đơn" thậm chí không phải perf_event_attr
là một dạng chung, phù hợp với cả các sự kiện SW và HW, đó là một sự kiện truy vấn của bạn - các sự kiện tương tự có thể đến từ các thiết bị khác nhau và chúng được tổng hợp .)
Ngoài ra một thông báo: struct perf_evsel
chỉ chứa 1 struct perf_evevent_attr
, nhưng nó cũng có một trường struct perf_evsel *leader;
- nó được lồng vào nhau. Có một tính năng của "các nhóm sự kiện (phân cấp)" trongperf_events
, khi bạn có thể gửi một loạt các quầy với nhau, để chúng có thể được so sánh với nhau, v.v. Không chắc thế nào nó hoạt động với các sự kiện độc lập với kernel
, core
, ubox
. Nhưng cái lồng perf_evsel
này là nó. Và, rất có thể, đó là cách perf
quản lý truy vấn của một số sự kiện cùng nhau.