diff options
| author | Davit Grigoryan <[email protected]> | 2026-04-12 01:05:57 +0000 |
|---|---|---|
| committer | Davit Grigoryan <[email protected]> | 2026-04-12 01:05:57 +0000 |
| commit | c3c124bfdf4384db3b6e852b517dc8828577a3a5 (patch) | |
| tree | 4dca37ffc13bf3939d9b051898fb131a22c44729 | |
| parent | 29d90a95ffa4287f58dc30a2e3488edf13d6c143 (diff) | |
impl thread compaction
| -rw-r--r-- | src/abstract_hardware_model.cc | 41 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 4 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 68 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 3 |
5 files changed, 95 insertions, 23 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index ed91a44..deebfd6 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -88,6 +88,47 @@ void warp_inst_t::compute_simd_sets(unsigned num_sets, unsigned set_width) { } } +void warp_inst_t::compute_simd_sets_compacted(unsigned num_sets, + unsigned set_width, + unsigned start_set) { + m_simd_sets.resize(num_sets); + // Initialize all sets as invalid + for (unsigned s = 0; s < num_sets; s++) { + simd_set_info &info = m_simd_sets[s]; + info.set_id = s; + info.warp_id = m_warp_id; + info.set_active_mask.reset(); + info.active_mask_in_warp.reset(); + info.num_active_threads = 0; + info.valid = false; + info.source_inst = NULL; + for (unsigned i = 0; i < MAX_WARP_SIZE; i++) info.thread_ids[i] = 0; + } + + // Collect active thread IDs + std::vector<unsigned> active_tids; + for (unsigned t = 0; t < m_config->warp_size; t++) { + if (m_warp_active_mask.test(t)) active_tids.push_back(t); + } + + // Pack active threads contiguously into sets starting at start_set + unsigned tid_idx = 0; + for (unsigned s = start_set; s < num_sets && tid_idx < active_tids.size(); + s++) { + simd_set_info &info = m_simd_sets[s]; + for (unsigned lane = 0; + lane < set_width && tid_idx < active_tids.size(); lane++) { + unsigned tid = active_tids[tid_idx]; + info.thread_ids[lane] = tid; + info.set_active_mask.set(lane); + info.active_mask_in_warp.set(tid); + info.num_active_threads++; + tid_idx++; + } + info.valid = true; + } +} + unsigned warp_inst_t::num_active_simd_sets() const { unsigned count = 0; for (unsigned i = 0; i < m_simd_sets.size(); i++) { diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index f191ab9..d3f0797 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1183,6 +1183,8 @@ class warp_inst_t : public inst_t { // SIMD lane partitioning void compute_simd_sets(unsigned num_sets, unsigned set_width); + void compute_simd_sets_compacted(unsigned num_sets, unsigned set_width, + unsigned start_set = 0); const std::vector<simd_set_info> &get_simd_sets() const { return m_simd_sets; } diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 17c7247..7b186aa 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -681,6 +681,10 @@ void shader_core_config::reg_options(class OptionParser *opp) { option_parser_register( opp, "-gpgpu_num_simd_sets", OPT_UINT32, &gpgpu_num_simd_sets, "Number of SIMD sets to partition lanes into (default = 1)", "1"); + option_parser_register( + opp, "-gpgpu_enable_compaction", OPT_BOOL, &gpgpu_enable_compaction, + "Enable thread compaction into fewer SIMD sets (default = disabled)", + "0"); for (unsigned j = 0; j < SPECIALIZED_UNIT_NUM; ++j) { std::stringstream ss; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index ea2d9b3..b0b1371 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1105,8 +1105,12 @@ warp_inst_t *shader_core_ctx::issue_warp(register_set &pipe_reg_set, m_stats->shader_cycle_distro[2 + (*pipe_reg)->active_count()]++; // Compute SIMD set assignments before functional execution if (m_config->gpgpu_simd_partitioning) { - (*pipe_reg)->compute_simd_sets(m_config->gpgpu_num_simd_sets, - m_config->simd_set_width); + if (m_config->gpgpu_enable_compaction) + (*pipe_reg)->compute_simd_sets_compacted( + m_config->gpgpu_num_simd_sets, m_config->simd_set_width, 0); + else + (*pipe_reg)->compute_simd_sets(m_config->gpgpu_num_simd_sets, + m_config->simd_set_width); } func_exec_inst(**pipe_reg); @@ -1209,7 +1213,8 @@ warp_inst_t *shader_core_ctx::issue_warp(register_set &pipe_reg_set, void shader_core_ctx::co_issue_warp(warp_inst_t *composite, const warp_inst_t *next_inst, const active_mask_t &active_mask, - unsigned warp_id, unsigned sch_id) { + unsigned warp_id, unsigned sch_id, + unsigned start_set) { // Free the co-issued warp's I-buffer entry m_warp[warp_id]->ibuffer_free(); assert(next_inst->valid()); @@ -1222,8 +1227,12 @@ void shader_core_ctx::co_issue_warp(warp_inst_t *composite, m_warp[warp_id]->get_streamID()); // Compute SIMD sets for the co-issued instruction - temp_inst.compute_simd_sets(m_config->gpgpu_num_simd_sets, - m_config->simd_set_width); + if (m_config->gpgpu_enable_compaction) + temp_inst.compute_simd_sets_compacted(m_config->gpgpu_num_simd_sets, + m_config->simd_set_width, start_set); + else + temp_inst.compute_simd_sets(m_config->gpgpu_num_simd_sets, + m_config->simd_set_width); // Functional execution for the co-issued warp's threads func_exec_inst(temp_inst); @@ -1718,12 +1727,16 @@ void scheduler_unit::cycle() { if (m_shader->m_config->gpgpu_simd_partitioning && co_issue_composite != NULL && co_issue_fu_type != exec_unit_type_t::MEM && co_issue_fu_type != exec_unit_type_t::NONE) { - // Count available (unused) sets in the composite + // Count available (unused) sets and find next free set unsigned available_sets = 0; + unsigned next_free_set = 0; const std::vector<simd_set_info> &primary_sets = co_issue_composite->get_simd_sets(); for (unsigned s = 0; s < primary_sets.size(); s++) { - if (!primary_sets[s].valid) available_sets++; + if (!primary_sets[s].valid) + available_sets++; + else + next_free_set = s + 1; // track end of used sets (for compaction) } if (available_sets > 0) { @@ -1733,6 +1746,8 @@ void scheduler_unit::cycle() { m_shader->get_gpu()->gpu_tot_sim_cycle, get_sid(), m_id, available_sets, co_issue_primary_warp_id); + unsigned set_width = m_shader->m_config->simd_set_width; + // Scan other warps for co-issue candidates for (std::vector<shd_warp_t *>::const_iterator iter2 = m_next_cycle_prioritized_warps.begin(); @@ -1802,26 +1817,34 @@ void scheduler_unit::cycle() { } if (cand_fu_type != co_issue_fu_type) continue; - // Get candidate's active mask and compute its SIMD sets + // Get candidate's active mask const active_mask_t &cand_mask = m_shader->get_active_mask(cand_warp_id, cand_inst); - // Build candidate's SIMD set info to check for overlap - warp_inst_t cand_temp(m_shader->m_config); - cand_temp = *cand_inst; - cand_temp.issue(cand_mask, cand_warp_id, 0, 0, 0, 0); - cand_temp.compute_simd_sets(m_shader->m_config->gpgpu_num_simd_sets, - m_shader->m_config->simd_set_width); + unsigned cand_sets_needed; + bool can_co_issue; - // Check set overlap with the current composite - if (warp_inst_t::simd_sets_overlap(co_issue_composite->get_simd_sets(), - cand_temp.get_simd_sets())) { - continue; // sets conflict, can't co-issue + if (m_shader->m_config->gpgpu_enable_compaction) { + // With compaction: just count sets needed, no overlap check + unsigned cand_active = cand_mask.count(); + cand_sets_needed = (cand_active + set_width - 1) / set_width; + can_co_issue = (cand_sets_needed <= available_sets); + } else { + // Without compaction: build temp sets and check overlap + warp_inst_t cand_temp(m_shader->m_config); + cand_temp = *cand_inst; + cand_temp.issue(cand_mask, cand_warp_id, 0, 0, 0, 0); + cand_temp.compute_simd_sets(m_shader->m_config->gpgpu_num_simd_sets, + m_shader->m_config->simd_set_width); + can_co_issue = + !warp_inst_t::simd_sets_overlap( + co_issue_composite->get_simd_sets(), + cand_temp.get_simd_sets()); + cand_sets_needed = cand_temp.num_active_simd_sets(); + if (cand_sets_needed > available_sets) can_co_issue = false; } - // Count candidate's sets to verify they fit - unsigned cand_sets_needed = cand_temp.num_active_simd_sets(); - if (cand_sets_needed > available_sets) continue; + if (!can_co_issue) continue; printf("SIMD_SETS: cycle %llu, core %u, sched %u: warp %u " "CO-ISSUED with primary warp %u (%u sets)\n", @@ -1832,9 +1855,10 @@ void scheduler_unit::cycle() { // Co-issue: functional execution, SIMT update, scoreboard, merge m_shader->co_issue_warp(co_issue_composite, cand_inst, cand_mask, - cand_warp_id, m_id); + cand_warp_id, m_id, next_free_set); available_sets -= cand_sets_needed; + next_free_set += cand_sets_needed; // Advance candidate warp's ibuffer warp(cand_warp_id).ibuffer_step(); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index c01abf1..31008ec 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1766,6 +1766,7 @@ class shader_core_config : public core_config { bool gpgpu_simd_partitioning; unsigned gpgpu_num_simd_sets; unsigned simd_set_width; // derived: warp_size / num_simd_sets + bool gpgpu_enable_compaction; unsigned n_simt_cores_per_cluster; unsigned n_simt_clusters; @@ -2537,7 +2538,7 @@ class shader_core_ctx : public core_t { unsigned warp_id, unsigned sch_id); void co_issue_warp(warp_inst_t *composite, const warp_inst_t *next_inst, const active_mask_t &active_mask, unsigned warp_id, - unsigned sch_id); + unsigned sch_id, unsigned start_set = 0); void create_front_pipeline(); void create_schedulers(); |
