Skip to content

Commit b6df8df

Browse files
authored
i#6684: Skip chunk invariants for dynamic core-sharded traces (#7689)
Skips drmemtrace invariant checks related to chunk instr counts and chunk ordinals when processing traces that are dynamically core-sharded. Such traces are not read from disk at all, therefore are not expected to have the same notion of chunks. Adds unit tests that verify that these relaxations are applied for dynamically core-sharded traces but not core-sharded-on-disk traces. Issue: #6684
1 parent 5b6d519 commit b6df8df

File tree

3 files changed

+124
-17
lines changed

3 files changed

+124
-17
lines changed

clients/drcachesim/tests/invariant_checker_test.cpp

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,17 @@ run_checker(const std::vector<memref_t> &memrefs, bool expect_error,
237237
return true;
238238
}
239239

240+
bool
241+
run_csod_checker(const std::vector<memref_t> &memrefs, bool expect_error,
242+
const error_info_t &expected_error_info = {},
243+
const std::string &toprint_if_fail = "")
244+
{
245+
return run_checker(memrefs, expect_error, expected_error_info, toprint_if_fail,
246+
/*serial_schedule_file=*/nullptr,
247+
/*set_skipped=*/false,
248+
/*core_sharded_on_disk=*/true);
249+
}
250+
240251
bool
241252
check_branch_target_after_branch()
242253
{
@@ -5047,7 +5058,7 @@ check_chunk_order(void)
50475058
if (!run_checker(memrefs, false))
50485059
return false;
50495060
}
5050-
// Incorrect: skip.
5061+
// Incorrect: skipped chunk ordinals.
50515062
{
50525063
std::vector<memref_t> memrefs = {
50535064
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
@@ -5069,7 +5080,7 @@ check_chunk_order(void)
50695080
"Failed to catch chunk ordinal skip"))
50705081
return false;
50715082
}
5072-
// Incorrect: no increase.
5083+
// Incorrect: no increase in chunk ordinal.
50735084
{
50745085
std::vector<memref_t> memrefs = {
50755086
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
@@ -5091,6 +5102,99 @@ check_chunk_order(void)
50915102
"Failed to catch chunk ordinal skip"))
50925103
return false;
50935104
}
5105+
// Correct: skip the check for dynamically core-sharded traces.
5106+
{
5107+
std::vector<memref_t> memrefs = {
5108+
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
5109+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT, 1),
5110+
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
5111+
gen_instr(TID_A, /*pc=*/1),
5112+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 0),
5113+
gen_instr(TID_A, /*pc=*/2),
5114+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 1),
5115+
gen_instr(TID_A, /*pc=*/3),
5116+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 1),
5117+
gen_exit(TID_A),
5118+
};
5119+
if (!run_csod_checker(memrefs, false))
5120+
return false;
5121+
}
5122+
// ... but do not skip the check for core-sharded-on-disk traces.
5123+
{
5124+
std::vector<memref_t> memrefs = {
5125+
gen_marker(TID_A, TRACE_MARKER_TYPE_FILETYPE, OFFLINE_FILE_TYPE_CORE_SHARDED),
5126+
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
5127+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT, 1),
5128+
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
5129+
gen_instr(TID_A, /*pc=*/1),
5130+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 0),
5131+
gen_instr(TID_A, /*pc=*/2),
5132+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 1),
5133+
gen_instr(TID_A, /*pc=*/3),
5134+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 1),
5135+
gen_exit(TID_A),
5136+
};
5137+
if (!run_csod_checker(memrefs, true,
5138+
{ "Chunks do not increase monotonically",
5139+
/*tid=*/TID_A,
5140+
/*ref_ordinal=*/9, /*last_timestamp=*/0,
5141+
/*instrs_since_last_timestamp=*/3 },
5142+
"Failed to catch chunk ordinal skip for csod"))
5143+
return false;
5144+
}
5145+
// Incorrect: inconsistent chunk instr count.
5146+
{
5147+
std::vector<memref_t> memrefs = {
5148+
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
5149+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT, 2),
5150+
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
5151+
gen_instr(TID_A, /*pc=*/1),
5152+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 0),
5153+
gen_instr(TID_A, /*pc=*/2),
5154+
gen_exit(TID_A),
5155+
};
5156+
if (!run_checker(memrefs, true,
5157+
{ "Chunk instruction counts are inconsistent",
5158+
/*tid=*/TID_A,
5159+
/*ref_ordinal=*/5, /*last_timestamp=*/0,
5160+
/*instrs_since_last_timestamp=*/1 },
5161+
"Failed to detect inconsistent chunk instr count"))
5162+
return false;
5163+
}
5164+
// Correct: skip the check for dynamically core-sharded traces.
5165+
{
5166+
std::vector<memref_t> memrefs = {
5167+
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
5168+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT, 2),
5169+
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
5170+
gen_instr(TID_A, /*pc=*/1),
5171+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 0),
5172+
gen_instr(TID_A, /*pc=*/2),
5173+
gen_exit(TID_A),
5174+
};
5175+
if (!run_csod_checker(memrefs, false))
5176+
return false;
5177+
}
5178+
// ... but do not skip for core-sharded-on-disk traces.
5179+
{
5180+
std::vector<memref_t> memrefs = {
5181+
gen_marker(TID_A, TRACE_MARKER_TYPE_FILETYPE, OFFLINE_FILE_TYPE_CORE_SHARDED),
5182+
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
5183+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT, 2),
5184+
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
5185+
gen_instr(TID_A, /*pc=*/1),
5186+
gen_marker(TID_A, TRACE_MARKER_TYPE_CHUNK_FOOTER, 0),
5187+
gen_instr(TID_A, /*pc=*/2),
5188+
gen_exit(TID_A),
5189+
};
5190+
if (!run_csod_checker(memrefs, true,
5191+
{ "Chunk instruction counts are inconsistent",
5192+
/*tid=*/TID_A,
5193+
/*ref_ordinal=*/5, /*last_timestamp=*/0,
5194+
/*instrs_since_last_timestamp=*/1 },
5195+
"Failed to detect inconsistent chunk instr count for csod"))
5196+
return false;
5197+
}
50945198
// Correct: skip when we did an explicit skip.
50955199
{
50965200
std::vector<memref_t> memrefs = {
@@ -5112,17 +5216,6 @@ check_chunk_order(void)
51125216
return true;
51135217
}
51145218

5115-
bool
5116-
run_csod_checker(const std::vector<memref_t> &memrefs, bool expect_error,
5117-
const error_info_t &expected_error_info = {},
5118-
const std::string &toprint_if_fail = "")
5119-
{
5120-
return run_checker(memrefs, expect_error, expected_error_info, toprint_if_fail,
5121-
/*serial_schedule_file=*/nullptr,
5122-
/*set_skipped=*/false,
5123-
/*core_sharded_on_disk=*/true);
5124-
}
5125-
51265219
bool
51275220
check_core_sharded()
51285221
{

clients/drcachesim/tools/invariant_checker.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ invariant_checker_t::relax_expected_read_count_check_for_kernel(per_shard_t *sha
289289
}
290290
#endif
291291

292+
bool
293+
invariant_checker_t::is_dynamically_core_sharded(per_shard_t *shard)
294+
{
295+
return core_sharded_ && !TESTANY(OFFLINE_FILE_TYPE_CORE_SHARDED, shard->file_type_);
296+
}
297+
292298
bool
293299
invariant_checker_t::parallel_shard_memref(void *shard_data, const memref_t &memref)
294300
{
@@ -434,8 +440,7 @@ invariant_checker_t::parallel_shard_memref(void *shard_data, const memref_t &mem
434440
}
435441
uint64_t adjusted_ref_count = shard->ref_count_;
436442
uint64_t adjusted_instr_count = shard->instr_count_;
437-
if (!core_sharded_ ||
438-
TESTANY(OFFLINE_FILE_TYPE_CORE_SHARDED, shard->file_type_)) {
443+
if (!is_dynamically_core_sharded(shard)) {
439444
adjusted_ref_count -= shard->dyn_injected_syscall_ref_count_;
440445
adjusted_instr_count -= shard->dyn_injected_syscall_instr_count_;
441446
} else {
@@ -626,7 +631,10 @@ invariant_checker_t::parallel_shard_memref(void *shard_data, const memref_t &mem
626631
"Stream interface version != trace marker");
627632
}
628633
if (memref.marker.type == TRACE_TYPE_MARKER &&
629-
memref.marker.marker_type == TRACE_MARKER_TYPE_CHUNK_FOOTER) {
634+
memref.marker.marker_type == TRACE_MARKER_TYPE_CHUNK_FOOTER &&
635+
// TODO i#7674: This check can be enabled using per-thread last chunk ordinals
636+
// when we have per-thread state tracking for dynamically core-sharded traces.
637+
!is_dynamically_core_sharded(shard)) {
630638
if (shard->skipped_instrs_) {
631639
report_if_false(shard,
632640
static_cast<int64_t>(memref.marker.marker_value) >=
@@ -704,7 +712,8 @@ invariant_checker_t::parallel_shard_memref(void *shard_data, const memref_t &mem
704712
"Stream interface chunk instr count != trace marker");
705713
}
706714
if (memref.marker.type == TRACE_TYPE_MARKER &&
707-
memref.marker.marker_type == TRACE_MARKER_TYPE_CHUNK_FOOTER) {
715+
memref.marker.marker_type == TRACE_MARKER_TYPE_CHUNK_FOOTER &&
716+
!is_dynamically_core_sharded(shard)) {
708717
report_if_false(
709718
shard,
710719
// Chunks in kernel trace template files are not defined by any fixed

clients/drcachesim/tools/invariant_checker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ class invariant_checker_t : public analysis_tool_t {
316316
relax_expected_read_count_check_for_kernel(per_shard_t *shard);
317317
#endif
318318

319+
// Returns whether the trace being processed is dynamically core-sharded. The
320+
// caller must use this only after the file type has been set in the per_shard_t.
321+
bool
322+
is_dynamically_core_sharded(per_shard_t *shard);
323+
319324
void *drcontext_ = dr_standalone_init();
320325
std::unordered_map<int, std::unique_ptr<per_shard_t>> shard_map_;
321326
// This mutex is only needed in parallel_shard_init to initialize shard_map_ with

0 commit comments

Comments
 (0)