From 8f03843850c264e65acd29786abbb5a3a02316c7 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Sun, 22 Aug 2021 03:44:22 +0530 Subject: [PATCH 01/14] initial commit, checking commands and importing libs --- output-parser/bottleneck_analysis.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 output-parser/bottleneck_analysis.py diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py new file mode 100644 index 000000000..b55f11fe7 --- /dev/null +++ b/output-parser/bottleneck_analysis.py @@ -0,0 +1,21 @@ +#import the necessary libraries +import matplotlib.pyplot as plt +import re +import sys +import linecache + +#checks for correct input format +if (len(sys.argv)!=2): + sys.exit("The format is 'python3 analyser.py '") + +filename=sys.argv[1] + +""" +The Basic idea here is to identfy the three most expensive kernels in your program +and then give you a rough idea where the basic bottle-neck is. This tool is based on +a part of the documentation for GP-GPUsim (MICRO 2012). Link to the above mentioned: http://gpgpu-sim.org/manual/index.php/Main_Page#:~:text=gpu_tot_sim_insn%20/%20wall_time-,Simple%20Bottleneck%20Analysis,-These%20performance%20counters + +The following is the implimentation theme of the tool: + + +""" \ No newline at end of file From 3adf478a52044972ea05226758b215b95e263cc6 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Sun, 22 Aug 2021 03:51:24 +0530 Subject: [PATCH 02/14] general outline in mind --- output-parser/bottleneck_analysis.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index b55f11fe7..249d0773e 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -6,8 +6,7 @@ #checks for correct input format if (len(sys.argv)!=2): - sys.exit("The format is 'python3 analyser.py '") - + sys.exit("The format is 'python3 bottleneck_analysis.py '") filename=sys.argv[1] """ @@ -16,6 +15,12 @@ a part of the documentation for GP-GPUsim (MICRO 2012). Link to the above mentioned: http://gpgpu-sim.org/manual/index.php/Main_Page#:~:text=gpu_tot_sim_insn%20/%20wall_time-,Simple%20Bottleneck%20Analysis,-These%20performance%20counters The following is the implimentation theme of the tool: +1. Make a dictionary with each thread launch's kernel_uid as key and line number as value. +2. Take out and all the necessary counters for bottle-neck analysis. +3. Subtract from the preceeding occurence as these are incremental, not kernel specific. +4. Group all the uids with same name together. +5. Get TOP-3 expensive kernels. +6. Plot the counters on the graph using plt. +""" -""" \ No newline at end of file From abaaa73fc61c387c35cd2b673f5a5159b5b4c97d Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Sun, 22 Aug 2021 04:30:17 +0530 Subject: [PATCH 03/14] uid_function, test it next --- output-parser/bottleneck_analysis.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 249d0773e..71fd02f3d 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -20,7 +20,23 @@ 3. Subtract from the preceeding occurence as these are incremental, not kernel specific. 4. Group all the uids with same name together. 5. Get TOP-3 expensive kernels. -6. Plot the counters on the graph using plt. +6. Plot the counters on the graph using plt for each kernel. """ + + +def uid_line(file): + pattern=re.compile("kernel_launch_uid = (\d*)") + res={} + for i,line in enumerate(open(file)): + for match in re.finditer(pattern,line): + capture_id=list(match.group(1))[0] + if capture_id not in res: + res[capture_id]={} + res[capture_id]["line"]=i + res[capture_id]["uid"]=capture_id + + return res + + From dfd560f30266df1e89e27c5d1d92cd11fa072e05 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Tue, 24 Aug 2021 18:14:42 +0530 Subject: [PATCH 04/14] uid tested --- output-parser/bottleneck_analysis.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 71fd02f3d..72ce1ecab 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -27,16 +27,18 @@ def uid_line(file): - pattern=re.compile("kernel_launch_uid = (\d*)") + pattern=re.compile("kernel_launch_uid = (\d+)") res={} for i,line in enumerate(open(file)): for match in re.finditer(pattern,line): - capture_id=list(match.group(1))[0] + capture_id=list(match.group(1)) + capture_id=int(''.join(capture_id)) if capture_id not in res: res[capture_id]={} res[capture_id]["line"]=i res[capture_id]["uid"]=capture_id return res - +res=uid_line(filename) +print(res[23]) From c30e3de4829e755529435ace566634b0fdbfbde2 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Wed, 25 Aug 2021 19:42:11 +0530 Subject: [PATCH 05/14] added the fetch_figure function --- output-parser/bottleneck_analysis.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 72ce1ecab..53f3a52a0 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -27,10 +27,10 @@ def uid_line(file): - pattern=re.compile("kernel_launch_uid = (\d+)") + uid_pattern=re.compile("kernel_launch_uid = (\d+)") res={} for i,line in enumerate(open(file)): - for match in re.finditer(pattern,line): + for match in re.finditer(uid_pattern,line): capture_id=list(match.group(1)) capture_id=int(''.join(capture_id)) if capture_id not in res: @@ -39,6 +39,17 @@ def uid_line(file): res[capture_id]["uid"]=capture_id return res -res=uid_line(filename) -print(res[23]) +def fetch_figure(fp,stat,kernel_line): + line_no=kernel_line + pattern=re.compile("^"+stat+" = ([+-]?[0-9]+\.?[0-9]*|\.[0-9]+)") + end_ker_pattern=re.compile("^.*END-of-Interconnect-DETAILS.*$") + matcher=re.match(pattern,linecache.getline(fp,line_no)) + while(not bool(matcher)): + if(bool(re.match(end_ker_pattern,linecache.getline(fp,line_no)))): + break + line_no+=1 + matcher=re.match(pattern,linecache.getline(fp,line_no)) + + figure=list(matcher.group(1)) + return figure From 306ecb1c337fa8c457316f6a8c15a3a021dc89cc Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Wed, 25 Aug 2021 19:57:54 +0530 Subject: [PATCH 06/14] fetch figure is unit tested and it throws excpetion if metric not found --- output-parser/bottleneck_analysis.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 53f3a52a0..9723e089f 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -1,4 +1,5 @@ #import the necessary libraries +from os import error import matplotlib.pyplot as plt import re import sys @@ -47,9 +48,16 @@ def fetch_figure(fp,stat,kernel_line): matcher=re.match(pattern,linecache.getline(fp,line_no)) while(not bool(matcher)): if(bool(re.match(end_ker_pattern,linecache.getline(fp,line_no)))): - break + raise Exception("There is no such metric, please check the white spaces and perform a spell check") line_no+=1 matcher=re.match(pattern,linecache.getline(fp,line_no)) figure=list(matcher.group(1)) + figure=float(''.join(figure)) return figure + +k=fetch_figure(filename,"gpu_stall_dramfull",29485) +print(k) +m=fetch_figure(filename,"gpu_stall_drafull",29485) +print(m) + From f09c74ca4338bf96bc5ef643ddf60455d9810e28 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 01:01:39 +0530 Subject: [PATCH 07/14] add_metric_by_uid implimented --- output-parser/bottleneck_analysis.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 9723e089f..51a2b3938 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -26,7 +26,7 @@ """ - +#this function gets the uid and line for each kernel def uid_line(file): uid_pattern=re.compile("kernel_launch_uid = (\d+)") res={} @@ -41,10 +41,12 @@ def uid_line(file): return res +#this kernel gets a particular figure from a particular kernel, given its starting line def fetch_figure(fp,stat,kernel_line): line_no=kernel_line pattern=re.compile("^"+stat+" = ([+-]?[0-9]+\.?[0-9]*|\.[0-9]+)") end_ker_pattern=re.compile("^.*END-of-Interconnect-DETAILS.*$") + matcher=re.match(pattern,linecache.getline(fp,line_no)) while(not bool(matcher)): if(bool(re.match(end_ker_pattern,linecache.getline(fp,line_no)))): @@ -56,8 +58,4 @@ def fetch_figure(fp,stat,kernel_line): figure=float(''.join(figure)) return figure -k=fetch_figure(filename,"gpu_stall_dramfull",29485) -print(k) -m=fetch_figure(filename,"gpu_stall_drafull",29485) -print(m) From bee74899241f0b9e7112b2a832141f17807d44ae Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 01:02:07 +0530 Subject: [PATCH 08/14] add_metric_by_uid implimented --- output-parser/bottleneck_analysis.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 51a2b3938..6c2d5ec9d 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -58,4 +58,14 @@ def fetch_figure(fp,stat,kernel_line): figure=float(''.join(figure)) return figure +def add_metric_by_uid(fp,res,metric): + for i in res: + try: + (res[i])[metric]=float(fetch_figure(fp,metric,(res[i])[metric])) + except: + print("adding "+metric+" as string") + (res[i])[metric]=fetch_figure(fp,metric,(res[i])[metric]) + + + From 2acfe8a946bfc299ffcbd3efcca14ed5d95007e0 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 02:21:16 +0530 Subject: [PATCH 09/14] add_metric_by_uid can handle string and floats both. Unit and Integration test done for this --- output-parser/bottleneck_analysis.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 6c2d5ec9d..d83b5b54d 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -44,7 +44,7 @@ def uid_line(file): #this kernel gets a particular figure from a particular kernel, given its starting line def fetch_figure(fp,stat,kernel_line): line_no=kernel_line - pattern=re.compile("^"+stat+" = ([+-]?[0-9]+\.?[0-9]*|\.[0-9]+)") + pattern=re.compile("^"+stat+" = (.*)") end_ker_pattern=re.compile("^.*END-of-Interconnect-DETAILS.*$") matcher=re.match(pattern,linecache.getline(fp,line_no)) @@ -55,17 +55,28 @@ def fetch_figure(fp,stat,kernel_line): matcher=re.match(pattern,linecache.getline(fp,line_no)) figure=list(matcher.group(1)) - figure=float(''.join(figure)) + figure=''.join(figure) return figure def add_metric_by_uid(fp,res,metric): for i in res: try: - (res[i])[metric]=float(fetch_figure(fp,metric,(res[i])[metric])) + + (res[i])[metric]=float(fetch_figure(fp,metric,(res[i])["line"])) except: - print("adding "+metric+" as string") - (res[i])[metric]=fetch_figure(fp,metric,(res[i])[metric]) + try: + (res[i])[metric]=fetch_figure(fp,metric,(res[i])["line"]) + except Exception as e : + print(e) + break + +res=uid_line(filename) +add_metric_by_uid(filename,res,"kernel_name") +add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") +print(res[1]) + + From 9f9f67cef0283fb4c1b2274d0557b4dc37abe147 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 14:26:23 +0530 Subject: [PATCH 10/14] norm_metric is implimented and tested, it throws err if strings are there --- output-parser/bottleneck_analysis.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index d83b5b54d..125300a32 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -1,5 +1,6 @@ #import the necessary libraries from os import error +from types import resolve_bases import matplotlib.pyplot as plt import re import sys @@ -61,7 +62,6 @@ def fetch_figure(fp,stat,kernel_line): def add_metric_by_uid(fp,res,metric): for i in res: try: - (res[i])[metric]=float(fetch_figure(fp,metric,(res[i])["line"])) except: try: @@ -70,6 +70,25 @@ def add_metric_by_uid(fp,res,metric): print(e) break +def add_metrics_list(fp,res,metrics): + for i in metrics: + add_metric_by_uid(fp,res,i) + +def norm_metric(res,metric): + + first_key=next(iter(res)) + if(isinstance(res[first_key][metric],str)): + raise Exception("metrics which are inserted as strings cannot be adjusted") + + lis=[] + for i in res: + lis.append((res[i])[metric]) + for i in range(len(lis)-1,0,-1): + lis[i]=lis[i]-lis[i-1] + m=0 + for i in res: + (res[i])[metric]=lis[m] + m=m+1 @@ -77,6 +96,7 @@ def add_metric_by_uid(fp,res,metric): res=uid_line(filename) add_metric_by_uid(filename,res,"kernel_name") add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") -print(res[1]) +norm_metric(res,"gpgpu_n_param_mem_insn") +print(res[2]) From 33ac6403e727b278c1393834447bc724450e8e32 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 15:03:32 +0530 Subject: [PATCH 11/14] grpby added, todo: cycle analysis and graphing --- output-parser/bottleneck_analysis.py | 34 ++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 125300a32..fbbafe3af 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -42,7 +42,7 @@ def uid_line(file): return res -#this kernel gets a particular figure from a particular kernel, given its starting line +#this function gets a particular figure from a particular kernel, given its starting line def fetch_figure(fp,stat,kernel_line): line_no=kernel_line pattern=re.compile("^"+stat+" = (.*)") @@ -59,21 +59,26 @@ def fetch_figure(fp,stat,kernel_line): figure=''.join(figure) return figure +# this function add a particular metric that you spicify, to the record of each kernel launch def add_metric_by_uid(fp,res,metric): for i in res: try: (res[i])[metric]=float(fetch_figure(fp,metric,(res[i])["line"])) except: try: - (res[i])[metric]=fetch_figure(fp,metric,(res[i])["line"]) + (res[i])[metric]=fetch_figure(fp,metric,(res[i])["line"]).strip() except Exception as e : print(e) break +# this is a function that a list of metrics to record of each kernel launch def add_metrics_list(fp,res,metrics): for i in metrics: add_metric_by_uid(fp,res,i) + +#this function is for the metrics that are essentially counters i.e. they are not kernel specific. +#These counters are the ones that are increamented hence need to be subtracted with their previous value. def norm_metric(res,metric): first_key=next(iter(res)) @@ -89,6 +94,27 @@ def norm_metric(res,metric): for i in res: (res[i])[metric]=lis[m] m=m+1 + + +#Above function but with a list +def norm_metric_list(res,metrics): + for i in metrics: + norm_metric(res,i) + +#Used for grouping the launch records on the basis of the metric specified. +def grpby_metric(res, metric): + grp_res={} + list_uni=[] + for i in res: + list_uni.append( (res[i])[metric] ) + list_uni=list(set(list_uni)) + for m in list_uni: + for k in res: + if(res[k][metric]==m): + if m not in grp_res: + grp_res[m]=[] + grp_res[m].append(res[k]) + return grp_res @@ -97,6 +123,6 @@ def norm_metric(res,metric): add_metric_by_uid(filename,res,"kernel_name") add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") norm_metric(res,"gpgpu_n_param_mem_insn") -print(res[2]) - +res=grpby_metric(res,"kernel_name") +print(res["_Z19vertex2normalKernel5ImageI6float33RefES2_"]) From 84e7f7dcc1f60ef410f2b67c673216849b908358 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Thu, 26 Aug 2021 15:15:24 +0530 Subject: [PATCH 12/14] cycle analysis done and tested --- output-parser/bottleneck_analysis.py | 39 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index fbbafe3af..35b2e97ee 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -115,14 +115,41 @@ def grpby_metric(res, metric): grp_res[m]=[] grp_res[m].append(res[k]) return grp_res + +def cycle_analysis(): + res=uid_line(filename) + + metrics = ["gpu_sim_cycle","kernel_name"] + add_metrics_list(filename,res,metrics) + grpd_res=grpby_metric(res,"kernel_name") + view={} + for i in grpd_res: + prop=0 + for q in grpd_res[i]: + prop=prop+q["gpu_sim_cycle"] + view[i]=prop + sorted_view={k:v for k,v in sorted(view.items(),key=lambda item: item[1])} + + x=[] + y=[] + for i in sorted_view: + x.append(i) + y.append(view[i]) + top3=[] + for k in range(-1,-4,-1): + top3.append(x[k]) + plt.barh(x,y) + plt.show() + return top3 -res=uid_line(filename) -add_metric_by_uid(filename,res,"kernel_name") -add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") -norm_metric(res,"gpgpu_n_param_mem_insn") -res=grpby_metric(res,"kernel_name") -print(res["_Z19vertex2normalKernel5ImageI6float33RefES2_"]) +# res=uid_line(filename) +# add_metric_by_uid(filename,res,"kernel_name") +# add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") +# norm_metric(res,"gpgpu_n_param_mem_insn") +# res=grpby_metric(res,"kernel_name") +# print(res["_Z19vertex2normalKernel5ImageI6float33RefES2_"]) +top3=cycle_analysis() From f1503a4692157d4ecd62a17d939f192c0c2b6063 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Fri, 27 Aug 2021 15:53:21 +0530 Subject: [PATCH 13/14] added the graphing and analysis capabilities --- output-parser/bottleneck_analysis.py | 52 +++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/output-parser/bottleneck_analysis.py b/output-parser/bottleneck_analysis.py index 35b2e97ee..4ac4d46fa 100644 --- a/output-parser/bottleneck_analysis.py +++ b/output-parser/bottleneck_analysis.py @@ -45,7 +45,7 @@ def uid_line(file): #this function gets a particular figure from a particular kernel, given its starting line def fetch_figure(fp,stat,kernel_line): line_no=kernel_line - pattern=re.compile("^"+stat+" = (.*)") + pattern=re.compile("^"+stat+"\s*=\s*(.*)") end_ker_pattern=re.compile("^.*END-of-Interconnect-DETAILS.*$") matcher=re.match(pattern,linecache.getline(fp,line_no)) @@ -116,13 +116,14 @@ def grpby_metric(res, metric): grp_res[m].append(res[k]) return grp_res +#this kernel adds the cycles taken up by each of the kernel in totality and plots a graph. I also returns a list of the three most heavy kernels def cycle_analysis(): res=uid_line(filename) - metrics = ["gpu_sim_cycle","kernel_name"] add_metrics_list(filename,res,metrics) grpd_res=grpby_metric(res,"kernel_name") view={} + #add cycles of each instance to figure out the heaviest for i in grpd_res: prop=0 for q in grpd_res[i]: @@ -136,20 +137,53 @@ def cycle_analysis(): x.append(i) y.append(view[i]) top3=[] + #get the top3 heaviest for k in range(-1,-4,-1): top3.append(x[k]) + #plot the kernel graph plt.barh(x,y) plt.show() return top3 - +def plot_metric(metric,res,kn): + x=[] + y=[] + for i in res: + x.append(i[metric]) + #print(len(x)) + for i in range(0,len(x)): + #print(i) + y.append(i) + plt.figure(figsize=(20,10)) + plt.bar(y,x) + plt.title(kn+"::"+metric) + plt.show() + + +def bottle_neck_analysis(kers): + res=uid_line(filename) + metrics=["gpgpu_n_stall_shd_mem","gpu_stall_dramfull","gpu_stall_icnt2sh ","kernel_name"] + tbn =["gpgpu_n_stall_shd_mem","gpu_stall_dramfull","gpu_stall_icnt2sh "] + add_metrics_list(filename,res,metrics) + norm_metric_list (res,tbn) + #print(res) + gprd_res=grpby_metric(res,"kernel_name") + tot=0 + pl_x=[] + pl_y=[] + for i in gprd_res: + pl_x.append(i) + pl_y.append(len(gprd_res[i])) + tot=tot+len(gprd_res[i]) + plt.barh(pl_x,pl_y) + + + for i in kers: + for m in tbn: + plot_metric(m,gprd_res[i],i) + return gprd_res -# res=uid_line(filename) -# add_metric_by_uid(filename,res,"kernel_name") -# add_metric_by_uid(filename,res,"gpgpu_n_param_mem_insn") -# norm_metric(res,"gpgpu_n_param_mem_insn") -# res=grpby_metric(res,"kernel_name") -# print(res["_Z19vertex2normalKernel5ImageI6float33RefES2_"]) top3=cycle_analysis() +bottle_neck_analysis(top3) From 642075396056480c127aec82f7c6a0b9af778619 Mon Sep 17 00:00:00 2001 From: electricSamarth Date: Fri, 27 Aug 2021 17:13:58 +0530 Subject: [PATCH 14/14] updated readme --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 9f9f6698f..7c260589d 100644 --- a/README.md +++ b/README.md @@ -411,6 +411,28 @@ process. # MISCELLANEOUS +## Bottleneck Analysis (Per-Kernel) +This is a simple, well commented script that can be used as a base for further kernel-by-kernel analysis. ** This is applicable for workloads that have minimal or no concurrent kernel execution. ** This script extracts the values required for [bottleneck analysis](http://gpgpu-sim.org/manual/index.php/Main_Page#:~:text=gpu_tot_sim_insn%20/%20wall_time-,Simple%20Bottleneck%20Analysis,-These%20performance%20counters) on per kernel basis. It plots these graphs, keep on closing the graph to acess the next graph: + +1) The first graph tells the total number of cycles by each of the kernels +2) The next graphs tells you the number of times that kernel is called +3) For the top 3 most "expensive" kernels on the basis of cycle, it plots the 3 counters mentioned in the bottleneck analysis. The title of each of these graphs is explainatory. each bar is essentially an instace of that kernel and on the y-axis is the contribution of that instance to that counter mentioned in the title in the format: "kernel_name::counter". + +To use this script you need Python (3.7 or higher is required as ordered dictionaries are launguage features from 3.7 and we use that) + +To run make sure that you have gp-gpusim output saved in a file to do that just pipe the tee command followed by the file name, something like this + +``` +./executable | tee anyFileName.log +``` + +Then run the python script: + +``` +python3 path_to_output-parser/bottleneck_analysis.py path_to_log_file +``` + + ## Speeding up the execution Some applications take several hours to execute on GPGPUSim. This is because the simulator has to dump the PTX, analyze them and get resource usage statistics. This can be avoided everytime we execute the program in the following way: