summaryrefslogtreecommitdiff
path: root/src/cuda-sim/ptx-stats.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuda-sim/ptx-stats.cc')
-rw-r--r--src/cuda-sim/ptx-stats.cc298
1 files changed, 298 insertions, 0 deletions
diff --git a/src/cuda-sim/ptx-stats.cc b/src/cuda-sim/ptx-stats.cc
new file mode 100644
index 0000000..2d18286
--- /dev/null
+++ b/src/cuda-sim/ptx-stats.cc
@@ -0,0 +1,298 @@
+/*
+ * Copyright © 2009 by Wilson W. L. Fung and the University of British Columbia,
+ * Vancouver, BC V6T 1Z4, All Rights Reserved.
+ *
+ * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE
+ * TERMS AND CONDITIONS.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h
+ * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda
+ * (property of NVIDIA). The files benchmarks/BlackScholes/ and
+ * benchmarks/template/ are derived from the CUDA SDK available from
+ * http://www.nvidia.com/cuda (also property of NVIDIA). The files from
+ * src/intersim/ are derived from Booksim (a simulator provided with the
+ * textbook "Principles and Practices of Interconnection Networks" available
+ * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by
+ * the corresponding legal terms and conditions set forth separately (original
+ * copyright notices are left in files from these sources and where we have
+ * modified a file our copyright notice appears before the original copyright
+ * notice).
+ *
+ * Using this version of GPGPU-Sim requires a complete installation of CUDA
+ * which is distributed seperately by NVIDIA under separate terms and
+ * conditions. To use this version of GPGPU-Sim with OpenCL requires a
+ * recent version of NVIDIA's drivers which support OpenCL.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the University of British Columbia nor the names of
+ * its contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only.
+ *
+ * 5. No nonprofit user may place any restrictions on the use of this software,
+ * including as modified by the user, by any other authorized user.
+ *
+ * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung,
+ * Ali Bakhoda, George L. Yuan, at the University of British Columbia,
+ * Vancouver, BC V6T 1Z4
+ */
+
+#include "ptx_ir.h"
+#include "ptx_sim.h"
+#include "ptx-stats.h"
+#include "../option_parser.h"
+#include <stdio.h>
+#include <map>
+
+// external dependencies
+extern function_info *g_func_info;
+
+// options
+int enable_ptx_file_line_stats;
+char * ptx_line_stats_filename = NULL;
+
+void ptx_file_line_stats_options(option_parser_t opp)
+{
+ option_parser_register(opp, "-enable_ptx_file_line_stats", OPT_BOOL,
+ &enable_ptx_file_line_stats,
+ "Turn on PTX source line statistic profiling. (1 = On)", "1");
+ option_parser_register(opp, "-ptx_line_stats_filename", OPT_CSTR,
+ &ptx_line_stats_filename,
+ "Output file for PTX source line statistics.", "gpgpu_inst_stats.txt");
+}
+
+// implementations
+
+// defining a PTX source line = filename + line number
+class ptx_file_line
+{
+public:
+ ptx_file_line(const char* s, int l){
+ if( s == NULL )
+ st = "NULL_NAME";
+ else
+ st = s;
+ line = l;
+ }
+
+ bool operator<(const ptx_file_line &other) const {
+ if( st == other.st ) {
+ if( line < other.line )
+ return true;
+ else
+ return false;
+ } else {
+ return st < other.st;
+ }
+ }
+
+ bool operator==(const ptx_file_line &other) const {
+ return (st==other.st) and (line==other.line);
+ }
+
+ std::string st;
+ unsigned line;
+};
+
+// holds all statistics collected for a singe PTX source line
+class ptx_file_line_stats
+{
+public:
+ ptx_file_line_stats()
+ : exec_count(0), latency(0), dram_traffic(0),
+ smem_n_way_bank_conflict_total(0), smem_warp_count(0),
+ gmem_n_access_total(0), gmem_warp_count(0), exposed_latency(0),
+ warp_divergence(0)
+ { }
+
+ unsigned long exec_count;
+ unsigned long long latency;
+ unsigned long long dram_traffic;
+ unsigned long long smem_n_way_bank_conflict_total; // total number of banks accessed by this instruction
+ unsigned long smem_warp_count; // number of warps accessing shared memory
+ unsigned long long gmem_n_access_total; // number of uncoalesced access in total from this instruction
+ unsigned long gmem_warp_count; // number of warps causing these uncoalesced access
+ unsigned long long exposed_latency; // latency exposed as pipeline bubbles (attributed to this instruction)
+ unsigned long long warp_divergence; // number of warp divergence occured at this instruction
+};
+
+static std::map<ptx_file_line, ptx_file_line_stats> ptx_file_line_stats_tracker;
+
+// output statistics to a file
+void ptx_file_line_stats_write_file()
+{
+ // check if stat collection is turned on
+ if (enable_ptx_file_line_stats == 0) return;
+
+ std::map<ptx_file_line, ptx_file_line_stats>::iterator it;
+ FILE * pfile;
+
+ pfile = fopen(ptx_line_stats_filename, "w");
+ fprintf(pfile,"kernel line : count latency dram_traffic smem_bk_conflicts smem_warp gmem_access_generated gmem_warp exposed_latency warp_divergence\n");
+ for( it=ptx_file_line_stats_tracker.begin(); it != ptx_file_line_stats_tracker.end(); it++ ) {
+ fprintf(pfile, "%s %i : ", it->first.st.c_str(), it->first.line);
+ fprintf(pfile, "%lu ", it->second.exec_count);
+ fprintf(pfile, "%llu ", it->second.latency);
+ fprintf(pfile, "%llu ", it->second.dram_traffic);
+ fprintf(pfile, "%llu ", it->second.smem_n_way_bank_conflict_total);
+ fprintf(pfile, "%lu ", it->second.smem_warp_count);
+ fprintf(pfile, "%llu ", it->second.gmem_n_access_total);
+ fprintf(pfile, "%lu ", it->second.gmem_warp_count);
+ fprintf(pfile, "%llu ", it->second.exposed_latency);
+ fprintf(pfile, "%llu ", it->second.warp_divergence);
+ fprintf(pfile, "\n");
+ }
+ fflush(pfile);
+ fclose(pfile);
+}
+
+// attribute one more execution count to this ptx instruction
+// counting the number of threads (not warps) executing this instruction
+void ptx_file_line_stats_add_exec_count(const ptx_instruction *pInsn)
+{
+ ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())].exec_count += 1;
+}
+
+// attribute pipeline latency to this ptx instruction (specified by the pc)
+// pipeline latency is the number of cycles a warp with this instruction spent in the pipeline
+void ptx_file_line_stats_add_latency(void * ptx_thd, unsigned pc, unsigned latency)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())].latency += latency;
+}
+
+// attribute dram traffic to this ptx instruction (specified by the pc)
+// dram traffic is counted in number of requests
+void ptx_file_line_stats_add_dram_traffic(unsigned pc, unsigned dram_traffic)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())].dram_traffic += dram_traffic;
+}
+
+// attribute the number of shared memory access cycles to a ptx instruction
+// counts both the number of warps doing shared memory access and the number of cycles involved
+void ptx_file_line_stats_add_smem_bank_conflict(void * ptx_thd, unsigned pc, unsigned n_way_bkconflict)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ ptx_file_line_stats& line_stats = ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())];
+ line_stats.smem_n_way_bank_conflict_total += n_way_bkconflict;
+ line_stats.smem_warp_count += 1;
+}
+
+// attribute a non-coalesced mem access to a ptx instruction
+// counts both the number of warps causing this and the number of memory requests generated
+void ptx_file_line_stats_add_uncoalesced_gmem(void * ptx_thd, unsigned pc, unsigned n_access)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ ptx_file_line_stats& line_stats = ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())];
+ line_stats.gmem_n_access_total += n_access;
+ line_stats.gmem_warp_count += 1;
+}
+
+// a class that tracks the inflight memory instructions of a shader core
+// and attributes exposed latency to those instructions when signaled to do so
+class ptx_inflight_memory_insn_tracker
+{
+public:
+ typedef std::map<const ptx_instruction *, int> insn_count_map;
+
+ void add_count(const ptx_instruction * pInsn, int count = 1)
+ {
+ ptx_inflight_memory_insns[pInsn] += count;
+ }
+
+ void sub_count(const ptx_instruction * pInsn, int count = 1)
+ {
+ insn_count_map::iterator i_insncount;
+ i_insncount = ptx_inflight_memory_insns.find(pInsn);
+
+ assert(i_insncount != ptx_inflight_memory_insns.end());
+
+ i_insncount->second -= count;
+
+ if (i_insncount->second <= 0) {
+ ptx_inflight_memory_insns.erase(i_insncount);
+ }
+ }
+
+ void attribute_exposed_latency(int count = 1)
+ {
+ insn_count_map &exlat_insnmap = ptx_inflight_memory_insns;
+ insn_count_map::const_iterator i_exlatinsn;
+
+ i_exlatinsn = exlat_insnmap.begin();
+ for (; i_exlatinsn != exlat_insnmap.end(); ++i_exlatinsn) {
+ const ptx_instruction *pInsn = i_exlatinsn->first;
+ ptx_file_line_stats& line_stats = ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())];
+ line_stats.exposed_latency += count;
+ }
+ }
+
+ insn_count_map ptx_inflight_memory_insns;
+};
+
+static ptx_inflight_memory_insn_tracker *inflight_mem_tracker = NULL;
+
+void ptx_file_line_stats_create_exposed_latency_tracker(int n_shader_cores)
+{
+ inflight_mem_tracker = new ptx_inflight_memory_insn_tracker[n_shader_cores];
+}
+
+// add an inflight memory instruction
+void ptx_file_line_stats_add_inflight_memory_insn(int sc_id, unsigned pc)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ inflight_mem_tracker[sc_id].add_count(pInsn);
+}
+
+// remove an inflight memory instruction
+void ptx_file_line_stats_sub_inflight_memory_insn(int sc_id, unsigned pc)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ inflight_mem_tracker[sc_id].sub_count(pInsn);
+}
+
+// attribute an empty cycle in the pipeline (exposed latency) to the ptx memory instructions in flight
+void ptx_file_line_stats_commit_exposed_latency(int sc_id, int exposed_latency)
+{
+ assert(exposed_latency > 0);
+ inflight_mem_tracker[sc_id].attribute_exposed_latency(exposed_latency);
+}
+
+// attribute the number of warp divergence to a ptx instruction
+void ptx_file_line_stats_add_warp_divergence(unsigned pc, unsigned n_way_divergence)
+{
+ const ptx_instruction *pInsn = function_info::pc_to_instruction(pc);
+
+ ptx_file_line_stats& line_stats = ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(), pInsn->source_line())];
+ line_stats.warp_divergence += n_way_divergence;
+}
+