├── .gitignore
├── .gitmodules
├── LICENSE
├── README
├── README.md
├── after_run
├── README
├── graph
│ ├── README
│ ├── cg_histogram.py
│ └── cg_pa_histogram.py
├── make_physical_trace.py
├── make_physical_trace_ts.py
└── mix_vpmap.py
├── run_script
├── README
├── SeqW1G4K
├── check.sh
├── getopt.sh
└── run_script.sh
└── test
├── Synthetic_Workload
├── hashmap
├── hashmap.cpp
├── heap
├── heap.c
├── indirect_delta
├── indirect_delta.c
├── strided_latjob
├── strided_latjob.c
├── true_random
└── true_random.c
└── test_synthetic.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *.deb
2 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "valgrind"]
2 | path = valgrind
3 | url = https://github.com/dgist-datalab/valgrind_cachetrace
4 | branch = master
5 | [submodule "kernel"]
6 | path = kernel
7 | url = https://github.com/dgist-datalab/cxl-kernel
8 | branch = cxl-minjae
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [2023] [Minjae Kim]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | This tool generates a virtual/physical address trace of the target application.
2 |
3 | [How to use]
4 | Step 1. Install Valgrind
5 | Go to valgrind/ dir and follow the install manual in the README.
6 | ** Note **
7 | In the latest commit, Valgrind prints out timestamps of boot time for each trace line.
8 | If you don't want, comment out ./valgrind/callgrind/sim.c:153.
9 | //#define TRACE_TIMESTAMP
10 |
11 | Step 2. Install kernel in your system
12 | Go to kernel/ dir and run install.sh to install kernel build files.
13 | If you don't need physical trace, then skip Step 2.
14 |
15 | Step 3. Run target application with our script to generate raw trace file.
16 | You can use run_script.sh in the run_script/ dir.
17 | When you run run_script.sh with the target executable file as an input,
18 | the script will run Valgrind to generate after-cache virtual trace
19 | and send the target pid to the kernel to generate Virtual-Phyiscal mapping.
20 | Detailed manual is in the README in run_script/.
21 |
22 | In the current version, you can run only one target program at once for physical trace.
23 |
24 | Step 4. Create the physical address trace from raw trace files
25 | run_script.sh in Step 3 includes this Step 4.
26 |
27 | After step 3, you can get raw trace file, [.vout].
28 | In step 4, you can get the physical trace file [.pout] by using the python script.
29 | Detailed manual is in the README in after_run/.
30 |
31 | After step 4, you will get [.pout] file as a final output.
32 | Format: [Read/Write] [Physical Address]
33 | Example:
34 | ...
35 | R 0x1234
36 | W 0x2345
37 | ...
38 |
39 | You can plot some graphs with trace files by using after_run/graph/*.py
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Trace Generator (Memory Tracing Tool)
2 | A memory tracing tool generating a virtual/physical address trace of the target aplication.
3 | This repository is focused on working together as a part of the [CXL-flash Design Tools](https://github.com/spypaul/MQSim_CXL) used in our research paper, _Overcoming the Memory Wall with CXL-Enabled SSDs_.
4 |
5 | ## Goal
6 | The goal of this memory tracing tool is generating raw memory trace files (`*.vout` or `*.pout`).
7 | To use MQSim_CXL in [CXL-flash Design Tools](https://github.com/spypaul/MQSim_CXL), the raw trace files generated from this tool should be translated to `*.trace` files by using [Trace Translator](https://github.com/spypaul/trace_translation).
8 |
9 | ## Installation
10 | This memory tracing tool is composed of three main components: a modified version of Valgrind, the Linux kernel, and scripts to facilitate its use.
11 | Repositories of the modified version of Valgrind and Linux kernel are submodules of this repository, and they follow their own licenses, GPL v2.
12 |
13 | ### The modified version of Valgrind
14 | 1. Clone [the github repository](https://github.com/dgist-datalab/valgrind_cachetrace/tree/040053890262abac1b504bbd5cd9ace8e2261a4e)
15 | ```
16 | $ git clone https://github.com/dgist-datalab/valgrind_cachetrace.git
17 | $ cd valgrind_cachetrace
18 | ```
19 | 2. Install the modified version of Valgrind
20 | ```
21 | $ ./autogen.sh
22 | $ ./configure
23 | $ make
24 | $ sudo make install
25 | ```
26 |
27 | ### Linux Kernel
28 | * If you don't need physical traces, don't need to install this Linux kernel.
29 | * The `defconfig` used in our forked kernel is located at `arch/x86/configs/ubuntu_defconfig`.
30 | 1. Clone [the github repository](https://github.com/dgist-datalab/cxl-kernel/tree/220990494efb831170a0dd60b45bd8afeea2d023)
31 | ```
32 | $ git clone https://github.com/dgist-datalab/cxl-kernel.git
33 | $ cd cxl-kernel
34 | ```
35 | 2. Build & install the Linux kernel
36 | ```
37 | $ cp arch/x86/configs/ubuntu_defconfig .config
38 | $ make bindeb-pkg -j64
39 | $ cd ../
40 | $ dpkg -i linux-headers-5.17.4-... linux-image-5.17.4-...
41 | $ reboot
42 | ...
43 | ```
44 |
45 | ## Test
46 | * `test/` directory includes a script generating raw trace files (`*.vout` or `*.pout`) of Synthetic workloads automatically.
47 | * When you run `test_synthetic.sh`, you can select which synthetic workload to run and generate only a virtual memory trace or both virtual/physical traces.
48 | ```
49 | $ cd test/
50 | $ sudo ./test_synthetic.sh
51 | ```
52 | * After generating the trace file, you can plot a rough figure showing the memory address distribution of the trace file.
53 | ```
54 | python3 after_run/graph/cg_histogram.py --input [.vout] --scatter 103
55 | python3 after_run/graph/cg_pa_histogram.py --input [.pout] --scatter 103
56 | ```
57 |
58 | * If you want to generate trace files of your target applications, run `run_script/run_script.sh` with your target applications following [README](https://github.com/dgist-datalab/trace_generator/tree/main/run_script).
59 |
60 | ### Test Output
61 | * Raw trace files: `*.vout`, `*.pout`.
62 | * These raw trace files are the input files for [Trace Translator](https://github.com/spypaul/trace_translation).
63 | * [Trace Translator](https://github.com/spypaul/trace_translation) translates these raw trace files to trace files for [MQSim_CXL](https://github.com/spypaul/MQSim_CXL).
64 |
--------------------------------------------------------------------------------
/after_run/README:
--------------------------------------------------------------------------------
1 | make_physical_trace.py
2 | usage: python3 make_physical_trace.py [trace.mix]
3 | output: trace.phyout
4 |
5 | the [.mix] trace file has two information. One is a virtual address trace, and the other is Virtual-Phyiscal mappings.
6 | This code combines two information and generates a physical address trace.
7 |
8 | The first line of [.pout] file:
9 | ok_cnt none_cnt ok/total
10 |
11 | make_physical_trace_ts.py
12 | usage: python3 make_physical_trace_ts.py [trace.mix]
13 | output: trace.phyout
14 |
15 | This script is the same as the one above, but is used when the [.mix] trace file contains timestamps.
16 | Only line 160 is different.
17 |
18 | mix_vpmap.py
19 | usage: python3 mix_vpmap.py [trace.vout]
20 | output: trace.mix
21 |
22 | This script makes [.mix] trace file by combining [trace.vout] and [trace.vpmap]
23 |
--------------------------------------------------------------------------------
/after_run/graph/README:
--------------------------------------------------------------------------------
1 | Plot graphs with generated trace.
2 |
3 | cg_histogram.py
4 | Input: [.vout] trace file from Step 3
5 | Output: [.eps] graph and log files
6 |
7 | python3 cg_histogram.py -i [trace.out]
8 | plot graph (VA - # of accesses)
9 | python3 cg_histogram.py -i [trace.out] --cdf
10 | plot sorted cdf graph (VA - # of accesses)
11 | python3 cg_histogram.py -i [trace.out] --scatter [sampling unit]
12 | plot graph (elapsed time - VA)
13 |
14 |
15 | cg_pa_histogram.py
16 | Input: [.pout] trace file from Step 4 and log files. You need to run cg_historam.py first to create log files.
17 | Output: [.eps] graph files.
18 |
19 | python3 cg_pa_histogram.py -i [trace.phyout]
20 | plot graph (PA - # of accesses)
21 | python3 cg_pa_histogram.py -i [trace.phyout] --cdf
22 | plot sorted cdf graph (PA - # of accesses)
23 | python3 cg_pa_histogram.py -i [trace.phyout] --scatter [sampling unit]
24 | plot graph (elapsed time - PA)
25 |
--------------------------------------------------------------------------------
/after_run/graph/cg_histogram.py:
--------------------------------------------------------------------------------
1 | from tokenize import group
2 | import matplotlib.pyplot as plt
3 | import numpy as np
4 | import sys
5 | import argparse
6 | from itertools import accumulate
7 |
8 | def file_len(fname):
9 | with open(fname) as f:
10 | for i, l in enumerate(f):
11 | pass
12 | return i + 1
13 |
14 | def save_log(fname, min, max, lower_bound, upper_bound, group_num, data=0):
15 | log_file = open(fname, 'w')
16 | log_file.write(str(hex(min)) + " " + str(hex(max)) + "\n")
17 | log_file.write(str(hex(lower_bound) + " " + str(hex(upper_bound))) + "\n")
18 | log_file.write("group_num " + str(group_num) + "\n")
19 | if data:
20 | log_file.write("ydata" + "\n")
21 | log_file.write(str(data).replace('[', '').replace(']', '').replace(',', ''))
22 | log_file.close()
23 |
24 | parser = argparse.ArgumentParser()
25 | parser.add_argument("-i", "--input", action='store', type=str, help='input file', default=False)
26 | parser.add_argument("-c", "--cdf", action='store_true', help='plot sorted cdf', default=False)
27 | parser.add_argument("-s", "--scatter", action='store', type=int, help='plot scattered graph', default=False)
28 | args = parser.parse_args()
29 | input_file_name = args.input
30 | scatter=0; cdf=0
31 | if args.scatter:
32 | scatter = 1
33 | print("plot scattered order-address graph")
34 | else:
35 | if args.cdf:
36 | cdf = 1
37 | print("plot sorted cdf graph")
38 | else:
39 | print("plot basic address histogram")
40 |
41 | input_file_name = args.input
42 | if input_file_name[-5:] != ".vout":
43 | print("input file [%s] is not .vout!" % (input_file_name))
44 | exit()
45 |
46 | linenum = file_len(input_file_name)
47 | print("linenum of %s: %d" % (input_file_name, linenum))
48 |
49 | # File open, and find min, max for specifying bound
50 | #input_file_name = "ldst_result"
51 | file = open(input_file_name, 'r')
52 | file.seek(0)
53 |
54 | i = 0
55 | min = 0xffffffffffffffff
56 | max = 0
57 | upper_bound = 0x1000000000
58 | lower_bound = 0x100000
59 | print("Find min/max of address..")
60 | while True:
61 | line = file.readline()
62 | if not line: break
63 | if line[0] == "=" or line[0] == "-": continue
64 | if (i % (linenum//1000)) == 0:
65 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
66 | #if i>100: exit()
67 |
68 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
69 | splitline = line.split("{")
70 | #del splitline[0]
71 | item = splitline[-1]
72 | #for item in splitline[::-1]:
73 | elem = item.split(" ")
74 | elem = ' '.join(elem).split()
75 | if elem[0] == 'R' or elem[0] == 'W':
76 | a = int(elem[1], 16)
77 | if a > max:
78 | if a < upper_bound: # Upper bound of interesting address
79 | max = a
80 | if a < min:
81 | if a > lower_bound: # Lower bound of interesting address
82 | min = a
83 | """
84 | line = line.replace('[R ', '').replace('[W ', '').replace(']', '').replace('\n',' ')
85 | a = int(line, 16)
86 |
87 | if a > max:
88 | if a < upper_bound: # Upper bound of interesting address
89 | max = a
90 | if a < min:
91 | if a > lower_bound: # Lower bound of interesting address
92 | min = a
93 | """
94 |
95 | i += 1
96 | #min= 0x100248; max= 0x158c60000
97 |
98 | print("min:", hex(min), "max:", hex(max))
99 | file.close()
100 |
101 | # File open, and make histogram (# of access per address group)
102 | file = open(input_file_name, 'r')
103 |
104 | va_pool_size = max-min
105 | #group_size = 4096 # Pagesize
106 | #va_group_num = va_pool_size // group_size
107 |
108 | group_num = 10000
109 | #group_num = va_group_num
110 | group_size = va_pool_size // group_num
111 | print("group_size:", group_size, "group_num:", group_num)
112 |
113 | if scatter:
114 | # create scatter list
115 | scope = max-min
116 | i = 0
117 | scatter = []
118 | print("Make scatter list..")
119 | while True:
120 | line = file.readline()
121 | if not line: break
122 | if line[0] == "=" or line[0] == "-": continue
123 | if (i % (linenum//1000)) == 0:
124 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
125 |
126 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
127 | elem = line.split("{")[-1].split(" ")
128 | elem = ' '.join(elem).split()
129 | if elem[0] == 'R' or elem[0] == 'W':
130 | a = int(elem[1], 16)
131 | if a >= upper_bound or a <= lower_bound:
132 | i += 1
133 | continue
134 | group_idx = round((a-min)/scope*group_num)
135 | scatter.append(group_idx)
136 | i += 1
137 | print("len(scatter):", len(scatter))
138 | file.close()
139 |
140 | # scatter plot
141 | samp_per = args.scatter
142 | samp = []
143 | for i in range(len(scatter)):
144 | if i % samp_per == 0:
145 | samp.append(scatter[i])
146 | print("len(samp):", len(samp))
147 |
148 | x = list(np.arange(0, len(samp), 1))
149 |
150 | #plt.rcParams["font.family"] = 'Times New Roman'
151 | plt.rcParams["font.size"] = 22
152 | plt.rcParams["figure.figsize"] = (8,5)
153 | plt.rc('legend', fontsize=18)
154 |
155 | fig, ax1 = plt.subplots(dpi=600)
156 | #plt.xticks(x, label, fontsize=20)
157 |
158 | x_ = x[:]
159 | scatter_ = samp[:]
160 | #x = x[:80]
161 | #hist = hist[:80]
162 | ax1.scatter(x, scatter_, c='black', s=1)
163 |
164 | #ax1.bar(x_, scatter_, width=0.2, edgecolor='black', linewidth=1, zorder=1)
165 |
166 | xlabel_name = 'Order of requests (sampled per ' + str(samp_per) + ' requests)'
167 | ylabel_name="Virtual address group \n(" + str(group_num) + " groups, "+str(group_size)+"B)"
168 | ax1.set_xlabel(xlabel_name)
169 | ax1.set_ylabel(ylabel_name)
170 | ax1.tick_params(axis='y', direction='in')
171 | ax1.set_ylim(0, group_num)
172 | id_str = "-scatter"+str(args.scatter)+"-g"+str(group_num)+"-"+str(group_size)
173 | fig_name = "./plot" + id_str + "_" + input_file_name[:-5] + "_va.png"
174 | fig.savefig(fig_name, bbox_inches='tight', format='png')
175 | log_file_name = input_file_name[:-5] + ".slog"
176 | save_log(log_file_name, min, max, lower_bound, upper_bound, group_num, data=scatter)
177 |
178 |
179 |
180 |
181 | else:
182 |
183 | scope = max-min
184 | i = 0
185 | hist = [0 for i in range(group_num+1)] # group: [0,100]
186 | print("Make histogram list..")
187 | while True:
188 | line = file.readline()
189 | if not line: break
190 | if line[0] == "=" or line[0] == "-": continue
191 | if (i % (linenum//1000)) == 0:
192 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
193 |
194 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
195 | elem = line.split("{")[-1].split(" ")
196 | elem = ' '.join(elem).split()
197 | if elem[0] == 'R' or elem[0] == 'W':
198 | a = int(elem[1], 16)
199 | if a >= upper_bound or a <= lower_bound:
200 | i += 1
201 | continue
202 | percent = round((a-min)/scope*group_num)
203 | hist[percent] += 1
204 |
205 | """
206 | # Integrate read/write as an access
207 | line = line.replace('[R ', '').replace('[W ', '').replace(']', '').replace('\n',' ')
208 | a = int(line, 16)
209 | if a >= upper_bound or a <= lower_bound:
210 | i += 1
211 | continue
212 |
213 | percent = round((a-min)/scope*group_num) # 100 groups
214 | #percent = round((a-min)/scope*1000) # 1000 groups
215 | hist[percent] += 1
216 | """
217 |
218 | i += 1
219 |
220 | file.close()
221 |
222 | if cdf == 1:
223 | sorted = 1
224 | hist.sort()
225 | sum_hist = sum(hist)
226 | cd = list(accumulate(hist))
227 | for i in range(len(cd)):
228 | cd[i] = cd[i]/sum_hist
229 | hist = cd
230 | else:
231 | sorted = 0
232 |
233 | # Make histogram
234 | x = list(np.arange(0, group_num+1, 1))
235 |
236 | #plt.rcParams["font.family"] = 'Times New Roman'
237 | plt.rcParams["font.size"] = 22
238 | plt.rcParams["figure.figsize"] = (8,5)
239 | plt.rc('legend', fontsize=18)
240 |
241 | fig, ax1 = plt.subplots(dpi=600)
242 |
243 | x_ = x[:]
244 | hist_ = hist[:]
245 | #x_ = x[20:80] # See 20% ~ 80%
246 | #hist_ = hist[20:80]
247 | ax1.bar(x_, hist_, width=0.2, edgecolor='black', linewidth=1, zorder=1)
248 |
249 | if sorted == 1:
250 | xlabel_name="Virtual address groups (" + str(group_num) + " groups, "+str(group_size)+"B, sorted)"
251 | else:
252 | xlabel_name="Virtual address groups (" + str(group_num) + " groups, "+str(group_size)+"B)"
253 | ax1.set_xlabel(xlabel_name)
254 | if cdf == 1:
255 | ax1.set_ylabel('CDF (# of accesses)')
256 | id_str = "-cdf-g"+str(group_num)+"-"+str(group_size)
257 | else:
258 | ax1.set_ylabel('# of accesses')
259 | id_str = "-g"+str(group_num)+"-"+str(group_size)
260 | ax1.tick_params(axis='y', direction='in')
261 |
262 | fig_name = "./hist" + id_str + "_" + input_file_name[:-5] + "_va.png"
263 | fig.savefig(fig_name, bbox_inches='tight', format='png')
264 |
265 | # Save min/max in a log file for calculating the address pool size
266 | if cdf == 1:
267 | log_file_name = input_file_name[:-5] + ".clog"
268 | else:
269 | log_file_name = input_file_name[:-5] + ".blog"
270 | save_log(log_file_name, min, max, lower_bound, upper_bound, group_num, data=hist)
271 |
--------------------------------------------------------------------------------
/after_run/graph/cg_pa_histogram.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import sys
4 | import argparse
5 | from itertools import accumulate
6 |
7 | def file_len(fname):
8 | with open(fname) as f:
9 | for i, l in enumerate(f):
10 | pass
11 | return i + 1
12 |
13 | def read_va_log(input_file_name, args, data_read = 0):
14 | # From VA histogram log file, calculate each group size
15 | if args.scatter > 0:
16 | log_ext = ".slog"
17 | elif args.cdf:
18 | log_ext = ".clog"
19 | else:
20 | log_ext = ".blog"
21 | va_log_file_name = input_file_name[:-5] + log_ext
22 | va_log_file = open(va_log_file_name, 'r')
23 | splitline = va_log_file.readline().split(" ")
24 | va_min = int(splitline[0], 16)
25 | va_max = int(splitline[1], 16)
26 | splitline = va_log_file.readline().split(" ")
27 | va_lower_bound = int(splitline[0], 16)
28 | va_upper_bound = int(splitline[1], 16)
29 | splitline = va_log_file.readline().split(" ")
30 | va_group_num = int(splitline[1], 10)
31 | va_log_file.readline()
32 | splitline = va_log_file.readline().split(" ")
33 | va_hist = []
34 | if data_read == 1 and args.cdf == 0:
35 | for y in splitline:
36 | va_hist.append(int(y))
37 | va_log_file.close()
38 | return va_min, va_max, va_lower_bound, va_upper_bound, va_group_num, va_hist
39 |
40 | parser = argparse.ArgumentParser()
41 | parser.add_argument("-i", "--input", action='store', type=str, help='input file', default=False)
42 | parser.add_argument("-c", "--cdf", action='store_true', help='plot sorted cdf', default=False)
43 | parser.add_argument("-s", "--scatter", action='store', type=int, help='plot scattered graph', default=False)
44 | args = parser.parse_args()
45 | input_file_name = args.input
46 | scatter=0; cdf=0
47 | if args.scatter:
48 | scatter = 1
49 | print("plot scattered order-address graph")
50 | else:
51 | if args.cdf:
52 | cdf = 1
53 | print("plot sorted cdf graph")
54 | else:
55 | print("plot basic address histogram")
56 |
57 | input_file_name = args.input
58 | #input_file_name = sys.argv[1]
59 | if input_file_name[-5:] != ".pout":
60 | print("input file [%s] is not .phyout!" % (input_file_name))
61 | exit()
62 |
63 | linenum = file_len(input_file_name)
64 | print("linenum of %s: %d" % (input_file_name, linenum))
65 |
66 | # File open, and find min, max for specifying bound
67 | file = open(input_file_name, 'r')
68 |
69 | i = 0
70 | min = 0xffffffffffffffff
71 | max = 0
72 | upper_bound = 0x1000000000
73 | #upper_bound = 0x350000000
74 | lower_bound = 0x100000
75 |
76 | print("Find min/max of address..")
77 | file.readline()
78 | while True:
79 | line = file.readline()
80 | if not line: break
81 | if line[0] == "=" or line[0] == "-": continue
82 | if (i % (linenum//1000)) == 0:
83 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
84 |
85 | line = line.replace('R ', '').replace('W ', '').replace('\n',' ')
86 | splitline = line.split(" ")
87 | a = int(splitline[0], 16)
88 |
89 | if a > max:
90 | if a < upper_bound: # Upper bound of interesting address
91 | max = a
92 | if a < min:
93 | if a > lower_bound: # Lower bound of interesting address
94 | min = a
95 |
96 | i += 1
97 |
98 | print("min:", hex(min), "max:", hex(max))
99 | group_num = 100000
100 |
101 | # From VA histogram log file, calculate each group size
102 | va_min, va_max, va_lower_bound, va_upper_bound, va_group_num, va_data = read_va_log(input_file_name, args, data_read = 1)
103 | #//print("sum(va_hist): %d" % (sum(va_hist)))
104 |
105 | va_pool_size = va_max - va_min
106 | va_group_size = va_pool_size // va_group_num
107 | pa_pool_size = max - min
108 | pa_group_size1 = pa_pool_size // group_num # static group size
109 | pa_group_size2 = va_group_size
110 | group_num2 = pa_pool_size // pa_group_size2
111 | group_weight = group_num2 // va_group_num // 2
112 | precise_plot = 0
113 | print("group_num (va/static_pa/precise_pa): %d/%d/%d, group_weight: %d, va_group_size: %d, pa_group_size (static/precise): %d/%d" % (va_group_num, group_num, group_num2, group_weight, va_group_size, pa_group_size1, pa_group_size2))
114 | if precise_plot == 0:
115 | print("For precise plotting, use same group size with virtual trace")
116 | group_num = group_num2
117 | group_size = pa_group_size2
118 | else:
119 | group_size = pa_group_size1
120 | # histogram 자체를 group_weight 개수만큼 나눠야 할 것 같긴 하다.
121 |
122 |
123 | # File open, and make histogram (# of access per address group)
124 | file.seek(0)
125 |
126 | man = 0 # manual size of axis
127 | man_range = 10000
128 | if scatter:
129 | scope = max-min
130 | i = 0
131 | scatter = []
132 | R_cnt = 0
133 | W_cnt = 0
134 |
135 | print("Make scatter list..")
136 | file.readline()
137 | while True:
138 | line = file.readline()
139 | if not line: break
140 | if line[0] == "=" or line[0] == "-": continue
141 | if (i % (linenum//1000)) == 0:
142 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
143 |
144 | # Integrate read/write as an access
145 | if line[0] == 'R':
146 | R_cnt += 1
147 | elif line[0] == 'W':
148 | W_cnt += 1
149 |
150 | line = line.replace('R ', '').replace('W ', '').replace('\n',' ')
151 | splitline = line.split(" ")
152 | a = int(splitline[0], 16)
153 | if a >= upper_bound or a <= lower_bound:
154 | i += 1
155 | continue
156 |
157 | group_idx = round((a-min)/scope*group_num)
158 | scatter.append(group_idx)
159 | i += 1
160 | print("len(scatter):", len(scatter))
161 | file.close()
162 |
163 | print("R_cnt: %d, W_cnt: %d, Total: %d" % (R_cnt, W_cnt, R_cnt+W_cnt))
164 | sum_scatter = sum(scatter)
165 | print("sum(scatter): %d" % (sum_scatter))
166 |
167 |
168 | # scatter plot
169 | samp_per = args.scatter
170 | samp = []
171 | for i in range(len(scatter)):
172 | if i % samp_per == 0:
173 | samp.append(scatter[i])
174 | print("len(samp):", len(samp))
175 |
176 | x = list(np.arange(0, len(samp), 1))
177 |
178 | figsize_x = 8; figsize_y = 5
179 | if precise_plot == 1:
180 | figsize_x = figsize_x * group_weight
181 | #plt.rcParams["font.family"] = 'Times New Roman'
182 | plt.rcParams["font.size"] = 22
183 | plt.rcParams["figure.figsize"] = (figsize_x, figsize_y)
184 | plt.rc('legend', fontsize=18)
185 |
186 | fig, ax1 = plt.subplots(dpi=600)
187 |
188 | #x_ = x[10000:15000]
189 | #hist_ = hist[10000:15000]
190 | x_ = x[:]
191 | scatter_ = samp[:]
192 | #x_ = x[20:80] # See 20% ~ 80%
193 | #hist_ = hist[20:80]
194 |
195 |
196 | print("plot..")
197 | ax1.scatter(x, scatter_, c='black', s=1)
198 | xlabel_name = 'Order of requests (sampled per ' + str(samp_per) + ' requests)'
199 | ylabel_name="Physical address group \n(" + str(group_num) + " groups, "+str(group_size)+"B)"
200 | ax1.set_xlabel(xlabel_name)
201 | ax1.set_ylabel(ylabel_name)
202 | ax1.tick_params(axis='y', direction='in')
203 | if man == 0:
204 | ax1.set_ylim(0, group_num)
205 | else:
206 | ax1.set_ylim(0, man_range) # add "man" in fig_name
207 |
208 | print("plot end. save..")
209 | id_str = "-scatter"+str(args.scatter)+"-g"+str(group_num)+"-"+str(group_size)
210 | if man == 0:
211 | fig_name = "./plot" + id_str + "_" + input_file_name[:-5] + "_pa.png"
212 | else:
213 | fig_name = "./manplot" + id_str + "_" + input_file_name[:-5] + "_pa.png"
214 | fig.savefig(fig_name, bbox_inches='tight', format='png')
215 |
216 | else:
217 | scope = max-min
218 | i = 0
219 | hist = [0 for i in range(group_num+1)] # group: [0,100]
220 | R_cnt = 0
221 | W_cnt = 0
222 |
223 | print("Make histogram list..")
224 | file.readline()
225 | while True:
226 | line = file.readline()
227 | if not line: break
228 | if line[0] == "=" or line[0] == "-": continue
229 | if (i % (linenum//1000)) == 0:
230 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
231 |
232 | # Integrate read/write as an access
233 | if line[0] == 'R':
234 | R_cnt += 1
235 | elif line[0] == 'W':
236 | W_cnt += 1
237 |
238 | line = line.replace('R ', '').replace('W ', '').replace('\n',' ')
239 | a = int(line, 16)
240 | if a >= upper_bound or a <= lower_bound:
241 | i += 1
242 | continue
243 |
244 | percent = round((a-min)/scope*group_num)
245 | hist[percent] += 1
246 |
247 | i += 1
248 |
249 | file.close()
250 | print("R_cnt: %d, W_cnt: %d, Total: %d" % (R_cnt, W_cnt, R_cnt+W_cnt))
251 | sum_hist = sum(hist)
252 | print("sum(hist): %d" % (sum_hist))
253 | va_hotgroup_cnt = 0; va_hotgroup_sum = 0
254 | hotgroup_cnt = 0; hotgroup_sum = 0
255 | for y in va_data:
256 | if y > 5000:
257 | va_hotgroup_cnt += 1
258 | va_hotgroup_sum += y
259 | for y in hist:
260 | if y > 5000:
261 | hotgroup_cnt += 1
262 | hotgroup_sum += y
263 | print("va_hotgroup_cnt: %d, hotgroup_cnt: %d" % (va_hotgroup_cnt, hotgroup_cnt))
264 | print("va_hotgroup_sum: %d, hotgroup_sum: %d" % (va_hotgroup_sum, hotgroup_sum))
265 | # group size가 어쨌든 4K pagesize보다는 크므로,
266 | # MMU가 VPN을 page 단위로 퍼뜨린다고 가정하면 더 퍼뜨리는 것처럼 보일 수 있다.
267 | # 이것까지 제대로 보려면, 애초에 VA hist에서 group size를 group_num=10000이 아니라
268 | # group_size=4000으로 해야 한다.
269 |
270 | # Sort and cdf
271 | from itertools import accumulate
272 |
273 | if cdf == 1:
274 | sorted = 1
275 | if man == 1:
276 | hist = hist[:man_range]
277 | hist.sort()
278 | sum_hist = sum(hist)
279 | cd = list(accumulate(hist))
280 | for i in range(len(cd)):
281 | cd[i] = cd[i]/sum_hist
282 | hist = cd
283 | else:
284 | sorted = 0
285 |
286 | # Make histogram
287 | if cdf == 0:
288 | x = list(np.arange(0, group_num+1, 1))
289 | else:
290 | if man == 1:
291 | x = list(np.arange(0, man_range, 1))
292 | else:
293 | x = list(np.arange(0, group_num+1, 1))
294 |
295 | figsize_x = 8; figsize_y = 5
296 | if precise_plot == 1:
297 | figsize_x = figsize_x * group_weight
298 | #plt.rcParams["font.family"] = 'Times New Roman'
299 | plt.rcParams["font.size"] = 22
300 | plt.rcParams["figure.figsize"] = (figsize_x, figsize_y)
301 | plt.rc('legend', fontsize=18)
302 |
303 | fig, ax1 = plt.subplots(dpi=600)
304 |
305 | #x_ = x[10000:15000]
306 | #hist_ = hist[10000:15000]
307 | x_ = x[:]
308 | hist_ = hist[:]
309 | #x_ = x[20:80] # See 20% ~ 80%
310 | #hist_ = hist[20:80]
311 |
312 |
313 | print("plot..")
314 | ax1.bar(x_, hist_, width=0.2, edgecolor='black', linewidth=1, zorder=1)
315 |
316 | if man == 1:
317 | if cdf == 1:
318 | ax1.set_xlim(man_range-10000, man_range) # add "man" in fig_name
319 | else:
320 | ax1.set_xlim(0, man_range) # add "man" in fig_name
321 |
322 | if sorted == 1:
323 | xlabel_name="Physical address groups (" + str(group_num) + " groups, "+str(group_size)+"B, sorted)"
324 | else:
325 | xlabel_name="Physical address groups (" + str(group_num) + " groups, "+str(group_size)+"B)"
326 | ax1.set_xlabel(xlabel_name)
327 | #ax1.set_xlabel('Physical address groups (1,000,000 groups)')
328 | if cdf == 1:
329 | ax1.set_ylabel('CDF (# of accesses)')
330 | id_str = "-cdf-g"+str(group_num)+"-"+str(group_size)
331 | else:
332 | ax1.set_ylabel('# of accesses')
333 | id_str = "-g"+str(group_num)+"-"+str(group_size)
334 | ax1.tick_params(axis='y', direction='in')
335 |
336 | print("plot end. save..")
337 | if man == 0:
338 | fig_name = "./hist" + id_str + "_" + input_file_name[:-5] + "_pa.png"
339 | else:
340 | fig_name = "./manhist" + id_str + "_" + input_file_name[:-5] + "_pa.png"
341 | fig.savefig(fig_name, bbox_inches='tight', format='png')
342 |
--------------------------------------------------------------------------------
/after_run/make_physical_trace.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import sys
4 |
5 | def file_len(fname):
6 | with open(fname) as f:
7 | for i, l in enumerate(f):
8 | pass
9 | return i + 1
10 |
11 | def find_close_mapping(x, a):
12 | target = 0
13 | close = 50
14 | small = 0
15 | big = len(a)-1
16 | for i in range(len(a)):
17 | if (a[i]) < x:
18 | small = i
19 | if a[i] >= x:
20 | big = i
21 | break
22 | diff_s = x-a[small]
23 | diff_b = a[big]-x
24 |
25 | if small == 0 and big == 0:
26 | target = small
27 | elif small == big and small > 0:
28 | target = big
29 | else:
30 | if diff_s < 0 or diff_b < 0:
31 | print("Error (diff_s: %d, diff_b: %d)" % (diff_s, diff_b))
32 | elif diff_s < close and diff_b < close:
33 | target = small if diff_s <= diff_b else big
34 | elif diff_s < close:
35 | target = small
36 | elif diff_b < close:
37 | target = big
38 | return target
39 |
40 |
41 |
42 | input_file_name = sys.argv[1]
43 | linenum = file_len(input_file_name)
44 | print("linenum of %s: %d" % (input_file_name, linenum))
45 |
46 | if input_file_name[-4:] != ".out":
47 | print("input file [%s] is not .out!" % (input_file_name))
48 | exit()
49 |
50 | raw_trace_file = open(input_file_name, 'r')
51 | for i in range(7):
52 | line = raw_trace_file.readline()
53 |
54 | i = 0
55 | d = {}
56 | d.clear()
57 | item_idx = {}
58 | item_idx.clear()
59 | item_cnt = 0
60 | map_cnt = 0
61 | vpn_cnt = 0
62 | exist_cnt = 0
63 |
64 | # make v2p map (dictionary)
65 | while True:
66 | line = raw_trace_file.readline()
67 | if not line: break
68 | if (i % (linenum//1000)) == 0:
69 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
70 |
71 | num_cg = line.count('[')
72 | num_kn = line.count('{')
73 | num_total = num_cg + num_kn
74 |
75 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
76 |
77 | splitline = line.split("{")
78 | del splitline[0]
79 |
80 | for item in splitline:
81 |
82 | elem = item.split(" ")
83 | elem = ' '.join(elem).split()
84 | if elem[0] == 'R' or elem[0] == 'W':
85 | cg_vaddr = int(elem[1], 16)
86 | else:
87 | map_cnt += 1
88 | kn_vpn = int(elem[2], 16)
89 | kn_pfn = int(elem[3], 16)
90 | if kn_vpn in d:
91 | d[kn_vpn].append([item_cnt, kn_pfn])
92 | exist_cnt += 1
93 | else:
94 | d[kn_vpn] = [[item_cnt, kn_pfn]]
95 | vpn_cnt += 1
96 | item_cnt += 1
97 |
98 | i += 1
99 |
100 | #raw_trace_file.close()
101 |
102 |
103 |
104 | # Second scan to translate Valgrind's virtual memory trace to the physical memory trace
105 | output_file_name = input_file_name[:-4] + ".phyout"
106 | mem_trace = open(output_file_name, 'w')
107 | raw_trace_file.seek(0)
108 |
109 | for i in range(7):
110 | line = raw_trace_file.readline()
111 |
112 | i = 0
113 | item_cnt = 0
114 | none_cnt = 0
115 | ok_cnt = 0
116 | find_flag = 0
117 | variable_map_cnt = 0
118 |
119 | while True:
120 | line = raw_trace_file.readline()
121 | if not line: break
122 | if (i % (linenum//1000)) == 0:
123 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
124 |
125 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
126 |
127 | splitline = line.split("{")
128 | del splitline[0]
129 |
130 | for item in splitline:
131 | elem = item.split(" ")
132 | elem = ' '.join(elem).split()
133 |
134 | if elem[0] == 'R' or elem[0] == 'W':
135 | cg_vaddr = int(elem[1], 16)
136 | cg_vpn = cg_vaddr // 4096
137 | cg_ofs = cg_vaddr & 0xfff
138 |
139 | if (d.get(cg_vpn) == None):
140 | none_cnt += 1
141 | else:
142 | val = d[cg_vpn]
143 | if len(val) > 1:
144 | idx_list = []
145 | for j in range(len(val)):
146 | idx_list.append(val[j][0])
147 | target_j = find_close_mapping(item_cnt, idx_list)
148 | kn_pfn = val[target_j][1]
149 | variable_map_cnt += 1
150 | else:
151 | kn_pfn = val[0][1];#(d.get(cg_vpn))[1]
152 |
153 | if (kn_pfn == None):
154 | none_cnt += 1
155 | print(hex(cg_vpn), "what?")
156 | exit()
157 | else:
158 | paddr = kn_pfn * 4096 + cg_ofs
159 | mem_trace.write(elem[0] + " " + str(hex(paddr)) + "\n")
160 | ok_cnt += 1
161 |
162 | item_cnt += 1
163 |
164 | i += 1
165 |
166 | print("ok: %d, none: %d, (%.1f%%)" % (ok_cnt, none_cnt, (ok_cnt/(ok_cnt+none_cnt))*100.0))
167 | mem_trace.seek(0)
168 | mem_trace.write(str(ok_cnt) + " " + str(none_cnt) + " " + str((ok_cnt/(ok_cnt+none_cnt))*100.0))
169 |
170 | raw_trace_file.close()
171 | mem_trace.close()
172 |
--------------------------------------------------------------------------------
/after_run/make_physical_trace_ts.py:
--------------------------------------------------------------------------------
1 | # If [.vout] trace file has timestamp, use this script.
2 | import matplotlib.pyplot as plt
3 | import numpy as np
4 | import sys
5 |
6 | def file_len(fname):
7 | with open(fname) as f:
8 | for i, l in enumerate(f):
9 | pass
10 | return i + 1
11 |
12 | def find_close_mapping(x, a):
13 | target = 0
14 | close = 50
15 | small = 0
16 | big = len(a)-1
17 | for i in range(len(a)):
18 | if (a[i]) < x:
19 | small = i
20 | if a[i] >= x:
21 | big = i
22 | break
23 | diff_s = x-a[small]
24 | diff_b = a[big]-x
25 |
26 | if small == 0 and big == 0:
27 | target = small
28 | elif small == big and small > 0:
29 | target = big
30 | else:
31 | if diff_s < 0 or diff_b < 0:
32 | print("Error (diff_s: %d, diff_b: %d)" % (diff_s, diff_b))
33 | elif diff_s < close and diff_b < close:
34 | target = small if diff_s <= diff_b else big
35 | elif diff_s < close:
36 | target = small
37 | elif diff_b < close:
38 | target = big
39 | return target
40 |
41 |
42 |
43 | input_file_name = sys.argv[1]
44 | linenum = file_len(input_file_name)
45 | print("linenum of %s: %d" % (input_file_name, linenum))
46 |
47 | if input_file_name[-4:] != ".mix":
48 | print("input file [%s] is not .mix!" % (input_file_name))
49 | exit()
50 |
51 | raw_trace_file = open(input_file_name, 'r')
52 | for i in range(7):
53 | line = raw_trace_file.readline()
54 |
55 | i = 0
56 | d = {}
57 | d.clear()
58 | item_idx = {}
59 | item_idx.clear()
60 | item_cnt = 0
61 | map_cnt = 0
62 | vpn_cnt = 0
63 | exist_cnt = 0
64 |
65 | # make v2p map (dictionary)
66 | while True:
67 | line = raw_trace_file.readline()
68 | if not line: break
69 | if (i % (linenum//1000)) == 0:
70 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
71 |
72 | num_cg = line.count('[')
73 | num_kn = line.count('{')
74 | num_total = num_cg + num_kn
75 |
76 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
77 |
78 | splitline = line.split("{")
79 | del splitline[0]
80 |
81 | for item in splitline:
82 |
83 | elem = item.split(" ")
84 | elem = ' '.join(elem).split()
85 | if elem[0] == 'R' or elem[0] == 'W':
86 | cg_vaddr = int(elem[1], 16)
87 | else:
88 | map_cnt += 1
89 | kn_vpn = int(elem[2], 16)
90 | kn_pfn = int(elem[3], 16)
91 | if kn_vpn in d:
92 | d[kn_vpn].append([item_cnt, kn_pfn])
93 | exist_cnt += 1
94 | else:
95 | d[kn_vpn] = [[item_cnt, kn_pfn]]
96 | vpn_cnt += 1
97 | item_cnt += 1
98 |
99 | i += 1
100 |
101 | #raw_trace_file.close()
102 |
103 |
104 |
105 | # Second scan to translate Valgrind's virtual memory trace to the physical memory trace
106 | output_file_name = input_file_name[:-4] + ".pout"
107 | mem_trace = open(output_file_name, 'w')
108 | raw_trace_file.seek(0)
109 |
110 | for i in range(7):
111 | line = raw_trace_file.readline()
112 |
113 | i = 0
114 | item_cnt = 0
115 | none_cnt = 0
116 | ok_cnt = 0
117 | find_flag = 0
118 | variable_map_cnt = 0
119 |
120 | while True:
121 | line = raw_trace_file.readline()
122 | if not line: break
123 | if (i % (linenum//1000)) == 0:
124 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
125 |
126 | line = line.replace(']', '}').replace('[', '{').replace('}', ' ').replace('\n',' ')
127 |
128 | splitline = line.split("{")
129 | del splitline[0]
130 |
131 | for item in splitline:
132 | elem = item.split(" ")
133 | elem = ' '.join(elem).split()
134 |
135 | if elem[0] == 'R' or elem[0] == 'W':
136 | cg_vaddr = int(elem[1], 16)
137 | cg_vpn = cg_vaddr // 4096
138 | cg_ofs = cg_vaddr & 0xfff
139 |
140 | if (d.get(cg_vpn) == None):
141 | none_cnt += 1
142 | else:
143 | val = d[cg_vpn]
144 | if len(val) > 1:
145 | idx_list = []
146 | for j in range(len(val)):
147 | idx_list.append(val[j][0])
148 | target_j = find_close_mapping(item_cnt, idx_list)
149 | kn_pfn = val[target_j][1]
150 | variable_map_cnt += 1
151 | else:
152 | kn_pfn = val[0][1];#(d.get(cg_vpn))[1]
153 |
154 | if (kn_pfn == None):
155 | none_cnt += 1
156 | print(hex(cg_vpn), "what?")
157 | exit()
158 | else:
159 | paddr = kn_pfn * 4096 + cg_ofs
160 | mem_trace.write(elem[0] + " " + str(hex(paddr)) + " " + elem[2] + "\n")
161 | ok_cnt += 1
162 |
163 | item_cnt += 1
164 |
165 | i += 1
166 |
167 | print("ok: %d, none: %d, (%.1f%%)" % (ok_cnt, none_cnt, (ok_cnt/(ok_cnt+none_cnt))*100.0))
168 | #mem_trace.seek(0)
169 | #mem_trace.write(str(ok_cnt) + " " + str(none_cnt) + " " + str((ok_cnt/(ok_cnt+none_cnt))*100.0))
170 |
171 | raw_trace_file.close()
172 | mem_trace.close()
173 |
--------------------------------------------------------------------------------
/after_run/mix_vpmap.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import sys
4 |
5 | def file_len(fname):
6 | with open(fname) as f:
7 | for i, l in enumerate(f):
8 | pass
9 | return i + 1
10 |
11 | input_file_name = sys.argv[1]
12 | if input_file_name[-5:] != ".vout":
13 | print("input file [%s] is not .vout!" % (input_file_name))
14 | exit()
15 | linenum = file_len(input_file_name)
16 | print("linenum of %s: %d" % (input_file_name, linenum))
17 |
18 | try:
19 | raw_trace_file = open(input_file_name, 'r')
20 | except:
21 | sys.stderr.write("No file: %s\n" % input_file_name)
22 | exit(1)
23 |
24 | for i in range(7):
25 | line = raw_trace_file.readline()
26 |
27 | vpmap_file_name = input_file_name[:-5] + ".vpmap"
28 | print("vpmap fname:", vpmap_file_name)
29 |
30 | try:
31 | vpmap_file = open(vpmap_file_name, 'r')
32 | except:
33 | sys.stderr.write("No file: %s\n" % vpmap_file_name)
34 | exit(1)
35 |
36 | output_file_name = input_file_name[:-5] + ".mix"
37 | mixed_file = open(output_file_name, 'w')
38 |
39 | i = 0
40 | vpmap_end = 0
41 | while True:
42 | line = raw_trace_file.readline()
43 | if not line: break
44 | if line[0] != "[":
45 | #print("[%d] %s" % (i, line), end="")
46 | i += 1
47 | continue
48 | #if line[0] == "=": break
49 | if (i % (linenum//1000)) == 0:
50 | print('\r', "%.0f%% [%d/%d]" % (i/linenum*100, i, linenum), end="")
51 | sline = line.replace(']', '').replace('\n', '')
52 | sline = sline.split(" ")
53 | #print("line:", line)
54 | #print("sline:", sline)
55 | #print(sline[-1])
56 | ts = float(sline[-1])
57 | #exit()
58 |
59 | # find earlier vpmap
60 | while vpmap_end == 0:
61 | ofs = vpmap_file.tell()
62 | mline = vpmap_file.readline()
63 | if not mline:
64 | vpmap_end = 1
65 | break
66 | msline = mline.replace('}', '').replace('\n', '')
67 | msline = msline.split(" ")
68 | map_ts = float(msline[-1])
69 | if map_ts < ts:
70 | mixed_file.write(mline)
71 | else:
72 | vpmap_file.seek(ofs)
73 | break
74 | mixed_file.write(line)
75 | i += 1
76 |
77 | raw_trace_file.close()
78 | vpmap_file.close()
79 | mixed_file.close()
80 |
81 |
--------------------------------------------------------------------------------
/run_script/README:
--------------------------------------------------------------------------------
1 | Use run_script.sh to start memory tracing. It generates virtual trace file with target executable program.
2 | It is a very simple script, so you can modify this script as you want.
3 | You can test the physical trace feature works well by running check.sh
4 |
5 | You can modify this script as you want.
6 | Line 58 and 63 is necessary.
7 | Line 58 runs valgrind to generate virtual memory address trace to the [.vout] file through stderr.
8 | and line 63 sends the pid of target process to the kernel.
9 | Upon receiving the target pid, the kernel outputs the VPN-PFN mapping information of the faulting address to the /proc/vpmap/vpmap.
10 |
11 | [How to use]
12 | ./run_script.sh --type [virtual/physical] --input [executable args..]
13 | NOTE: --input [] must be placed at the end of option
14 | Run [executable] with generating after-cache virtual address trace.
15 | virtual type: generate virtual address trace only.
16 | phyiscal type: generate virtual address trace & V2P mapping, and create physical address trace by mixing them.
17 |
18 | ./run_script.sh --type [virtual/physical] --pref --input [executable args..]
19 | NOTE: --input [] must be placed at the end of option
20 | Run [executable] with generating after-cache virtual address trace with cpu prefetcher in the valgrind cache simulator.
21 | To generate more accurate trace, recommend to use --pref option.
22 |
23 | Output:
24 | [trace_pref{ON/OFF}.vout] file: Virtual address trace
25 | [trace_pref{ON/OFF}.vpmap] file: V2P mapping information
26 | [trace_pref{ON/OFF}.mix] file: mixure of [.vout] and [.vpmap] following timestamps order
27 | [trace_pref{ON/OFF}.pout] file: Physical address trace
28 | [proclog.log] file: Redirection of process standard output
29 | [callgrind.out.#]: Output from vanilla Valgrind (We don't use. It's OK to remove these files)
30 |
--------------------------------------------------------------------------------
/run_script/SeqW1G4K:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/run_script/SeqW1G4K
--------------------------------------------------------------------------------
/run_script/check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cmd="./run_script.sh --input ./SeqW1G4K --type physical --pref"
4 | echo "\$$cmd"
5 | $cmd
6 |
--------------------------------------------------------------------------------
/run_script/getopt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # options:
4 | INPUT_FILE=""
5 | OPT_INT=0
6 | OPT_BOOL=False
7 | INPUT_FILE_YES=0
8 |
9 | # get options:
10 | echo "Note: '--input [args]' must be placed at the end"
11 | while (( "$#" )); do
12 | case "$1" in
13 | -i|--input)
14 | if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
15 | #INPUT_FILE=$2
16 | INPUT_FILE="${@:2}"
17 | INPUT_FILE_YES=1
18 | shift 2
19 | break
20 | else
21 | echo "Error: Argument for $1 is missing" >&2
22 | exit 1
23 | fi
24 | ;;
25 | -t|--type)
26 | if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
27 | TRACE_TYPE=$2
28 | shift 2
29 | else
30 | echo "Error: Argument for $1 is missing" >&2
31 | exit 1
32 | fi
33 | ;;
34 | -o|--outname)
35 | if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
36 | OUT_NAME=$2
37 | shift 2
38 | fi
39 | ;;
40 | -p|--pref)
41 | PREF=True
42 | shift
43 | ;;
44 | --nolog)
45 | NOLOG=True
46 | shift
47 | ;;
48 | -h|--help)
49 | echo "Usage: $0 -i [options]" >&2
50 | echo " -i | --input % (set input to ...)" >&2
51 | echo " -t | --type % (set trace type: virtual or physical)" >&2
52 | echo " -p | --pref (use cpu prefetcher in valgrind cache simulator)" >&2
53 | echo " --nolog (no redirection of standard output/error stream)" >&2
54 | exit 0
55 | ;;
56 | -*|--*) # unsupported flags
57 | echo "Error: Unsupported flag: $1" >&2
58 | echo "$0 -h for help message" >&2
59 | exit 1
60 | ;;
61 | *)
62 | echo "Error: Arguments with not proper flag: $1" >&2
63 | echo "$0 -h for help message" >&2
64 | exit 1
65 | ;;
66 | esac
67 | done
68 | echo "===parsed command line option==="
69 | echo " - input: ${INPUT_FILE}"
70 | echo " - type: ${TRACE_TYPE}"
71 | echo " - pref: ${PREF}"
72 | echo " - nolog: ${NOLOG}"
73 |
--------------------------------------------------------------------------------
/run_script/run_script.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$EUID" -ne 0 ]
4 | then echo "Please run as root or with sudo privileges"
5 | exit
6 | fi
7 |
8 | # drop page caches
9 | sync
10 | echo 3 > /proc/sys/vm/drop_caches
11 | echo 1 > /proc/sys/vm/compact_memory
12 | echo 3 > /proc/sys/vm/drop_caches
13 | echo 1 > /proc/sys/vm/compact_memory
14 |
15 | tooldir=$(git rev-parse --show-toplevel)
16 |
17 | # command
18 | arguments=$@
19 | . $tooldir/run_script/getopt.sh $arguments
20 | if [ $INPUT_FILE_YES -ne 1 ] || [ -z $TRACE_TYPE ]; then
21 | echo "No input or trace type!"
22 | echo " Args Example: -t/--type [virtual/physical] --pref -i/--input [\$INPUT_PROGRAM]"
23 | exit
24 | fi
25 |
26 | if [ "$TRACE_TYPE" == "virtual" ]; then
27 | echo "Trace type: Virtual address"
28 | echo "You can get trace file of Virtual address only"
29 | elif [ "$TRACE_TYPE" == "physical" ]; then
30 | echo "Trace type: Physical address"
31 | echo "You can get both trace files of Virtual address and V2P mapping. It requires modified kernel."
32 | echo 0 > /proc/vpmap/vpmap
33 | old_cg=$(pgrep -f callgrind | tail -n1)
34 | if [ -n "$old_cg" ]; then
35 | echo "[CAUTION] In the current version, only one process can be traced in the Physical Trace mode."
36 | echo "You should kill your old PIDs to run this script. The following PID list is assumed to be your old target processes:"
37 | old_cg_list=$(pgrep -f callgrind)
38 | echo "========="
39 | echo "$old_cg_list"
40 | echo "========="
41 | echo "Stop running.."
42 | exit
43 | fi
44 | fi
45 |
46 | if [ "$PREF" = True ]; then
47 | echo "Valgrind CPU Prefetch: ON"
48 | pref="yes"
49 | _pref="ON"
50 | else
51 | echo "Valgrind CPU Prefetch: OFF. Recommend using prefetch for more accurate trace.."
52 | pref="no"
53 | _pref="OFF"
54 | fi
55 |
56 | if [ -z "$OUT_NAME" ]; then
57 | logfile="trace_pref${_pref}"
58 | proclog="./proclog.log"
59 | else
60 | logfile="$OUT_NAME"
61 | proclog="./proclog_${OUT_NAME}.log"
62 | fi
63 |
64 | execname=$INPUT_FILE
65 | #proclog="./proclog.log"
66 | #logfile="trace_pref${_pref}"
67 | cglog="./$logfile.vout"
68 |
69 | if [ "$NOLOG" = True ]; then
70 | echo "NOLOG on!"
71 | proclog=""
72 | cglog=""
73 | fi
74 |
75 | start_time=`date +%s`
76 |
77 | # valgrind command
78 | echo "Run $execname with valgrind.."
79 | valgrind --tool=callgrind --simulate-wb=yes --simulate-hwpref=${pref} --log-fd=2 $execname > $proclog 2> $cglog &
80 |
81 | #target_pid=$(ps | grep callgrind | tail -n1 | awk '{print $1}')
82 | target_pid=$!
83 | pname=$(tr '\0' ' ' /sys/module/memory/parameters/target_pid
94 | echo $pidlist > /sys/module/memory/parameters/target_pid
95 | cat /sys/module/memory/parameters/target_pid
96 | fi
97 |
98 | while true; do
99 | if [ -d "/proc/$target_pid/" ]; then
100 | if [ "$TRACE_TYPE" == "physical" ]; then
101 | pidlist=$(ps -AL | grep callgrind | awk '{print $2}' | paste -s -d, -) # consider time lags of TIDs generation
102 | echo $pidlist > /sys/module/memory/parameters/target_pid
103 | fi
104 | sleep 0.3
105 | else
106 | break
107 | fi
108 | done
109 |
110 | wait $target_pid
111 | end_time=`date +%s`
112 |
113 | runtime=$((end_time-start_time))
114 | echo "runtime: $runtime (sec)"
115 |
116 | if [ "$TRACE_TYPE" == "physical" ]; then
117 | cat /proc/vpmap/vpmap > ./$logfile.vpmap
118 | echo 0 > /sys/module/memory/parameters/target_pid
119 | fi
120 |
121 | echo "Process end"
122 |
123 |
124 | if [ "$TRACE_TYPE" == "physical" ]; then
125 | echo "Make physical trace using virtual trace and V2P mapping.."
126 | python3 $tooldir/after_run/mix_vpmap.py ./$logfile.vout
127 | python3 $tooldir/after_run/make_physical_trace_ts.py ./$logfile.mix
128 | nline_vout=$(wc -l ./$logfile.vout | awk '{print $1}')
129 | nline_pout=$(wc -l ./$logfile.pout | awk '{print $1}')
130 | echo "# of lines ([.vout] / [.pout]): $nline_vout / $nline_pout"
131 | rm ./$logfile.mix
132 | fi
133 |
134 | read -r -p "Do you want to plot graph? [y/N] " response
135 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
136 | then
137 | echo "plot virtual trace graph.."
138 | python3 $tooldir/after_run/graph/cg_histogram.py --input $logfile.vout --scatter 103
139 | if [ "$TRACE_TYPE" == "physical" ]; then
140 | echo "plot physical trace graph.."
141 | python3 $tooldir/after_run/graph/cg_pa_histogram.py --input $logfile.pout --scatter 103
142 | fi
143 | fi
144 |
--------------------------------------------------------------------------------
/test/Synthetic_Workload/hashmap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/test/Synthetic_Workload/hashmap
--------------------------------------------------------------------------------
/test/Synthetic_Workload/hashmap.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | #define NUM_OPS (1UL << 24)
6 |
7 | int main(){
8 |
9 | unordered_map M;
10 |
11 | for(uint64_t i =0; i < NUM_OPS; i++){
12 | M[i] =i;
13 | }
14 |
15 |
16 | for(auto i =0 ; i < M.bucket_count(); i++){
17 | for(auto it = M.begin(i); it != M.end(i); it++){
18 | auto temp {it->first};
19 | auto temp2{it->second};
20 | temp += temp2;
21 | }
22 |
23 | }
24 | return 0;
25 | }
26 |
--------------------------------------------------------------------------------
/test/Synthetic_Workload/heap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/test/Synthetic_Workload/heap
--------------------------------------------------------------------------------
/test/Synthetic_Workload/heap.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define WORK_SIZE (1 << 27) //2G Bytes
7 |
8 |
9 | void add(uint64_t* h, uint64_t* lp, uint64_t value){
10 | uint64_t insert_at = *lp +1;
11 | *lp = insert_at;
12 | h[insert_at] = value;
13 |
14 | uint64_t p = insert_at;
15 |
16 | while(p != 0){
17 | uint64_t parent = (p -1)/2;
18 |
19 | if(h[parent] > h[p]){
20 | uint8_t temp = h[p];
21 | h[p] = h[parent];
22 | h[parent] = temp;
23 | p = parent;
24 | }else{
25 | return;
26 | }
27 | }
28 | }
29 | void delete(uint64_t* h, uint64_t* lp){
30 | h[0] = h[*lp];
31 | *lp = *lp -1;
32 |
33 | uint64_t p = 0;
34 |
35 | while(p <= *lp){
36 | uint64_t lc =2*p +1;
37 | uint64_t rc =2*p +2;
38 |
39 | if(lc <= *lp){
40 | if( lc!= *lp ){
41 | uint64_t ep = 0;
42 |
43 | if(h[lc] > h[rc]) ep = rc;
44 | else ep = lc;
45 |
46 | if(h[p] > h[ep]){
47 | int8_t temp = h[p];
48 | h[p] = h[ep];
49 | h[ep] = temp;
50 | p = ep;
51 |
52 | }else{
53 | return;
54 | }
55 |
56 | }else{
57 | if(h[p] > h[lc]){
58 | uint8_t temp = h[p];
59 | h[p] = h[lc];
60 | h[lc] = temp;
61 | p = lc;
62 | }
63 | else{
64 | return;
65 | }
66 | }
67 |
68 | }else{
69 | return;
70 | }
71 |
72 |
73 | }
74 |
75 |
76 | }
77 |
78 | int main(){
79 | uint64_t last_position = 0;
80 |
81 | uint64_t* h = (uint64_t*)malloc(sizeof(uint64_t)*WORK_SIZE);
82 |
83 | h[0] = (uint64_t)rand()+1;
84 |
85 |
86 | for(uint64_t i = 0; i < WORK_SIZE -1 ; i++){
87 | if (i % (1<<15) == 1){
88 | delete(h, &last_position);
89 | }
90 | add(h, &last_position, (uint64_t)rand()+1);
91 | //printf("%lu ", last_position);
92 | }
93 |
94 | // for(uint64_t i = 0; i < WORK_SIZE ; i++){
95 | // printf("%lu ", h[i]);
96 | // }
97 |
98 |
99 | return 0;
100 | }
--------------------------------------------------------------------------------
/test/Synthetic_Workload/indirect_delta:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/test/Synthetic_Workload/indirect_delta
--------------------------------------------------------------------------------
/test/Synthetic_Workload/indirect_delta.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #define ROW_SIZE (4UL)
5 | #define COL_SIZE (4UL)
6 |
7 | #define WORK_SET (1UL << 22)
8 |
9 |
10 | int main(){
11 |
12 | uint8_t*** ALL = (uint8_t***) malloc(WORK_SET*sizeof(uint8_t**));
13 |
14 | for(uint64_t ops =0; ops < WORK_SET; ops++){
15 |
16 |
17 | uint8_t** M = (uint8_t**)malloc(ROW_SIZE*sizeof(uint8_t*));
18 |
19 | for(uint64_t i =0; i < ROW_SIZE; i++){
20 | M[i] = (uint8_t*)malloc(COL_SIZE*sizeof(uint8_t));
21 | }
22 | ALL[ops] = M;
23 |
24 | }
25 |
26 | for(uint64_t ops = 0 ; ops < WORK_SET - 3; ops += 3){
27 | uint8_t** M = ALL[ops];
28 | uint8_t** M2 = ALL[ops+1];
29 | uint8_t**M3 = ALL[ops+2];
30 |
31 | for(uint64_t i =0; i < ROW_SIZE; i++){
32 | for(uint64_t j = 0; j < COL_SIZE; j++){
33 | for(uint64_t k =0; k < ROW_SIZE; k++){
34 | M3[i][j] = M[i][k] * M2[k][j];
35 | }
36 | }
37 | }
38 | }
39 |
40 |
41 |
42 | return 0;
43 | }
44 |
--------------------------------------------------------------------------------
/test/Synthetic_Workload/strided_latjob:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/test/Synthetic_Workload/strided_latjob
--------------------------------------------------------------------------------
/test/Synthetic_Workload/strided_latjob.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define WORK_SIZE (1L << 33) //1G Bytes
7 | #define ACCESS_SIZE 64L //64 Bytes
8 | #define STRIDE_SIZE (64L*16) //64 Bytes
9 | #define ACCESS_COUNT (WORK_SIZE/STRIDE_SIZE)
10 |
11 |
12 | int main(){
13 | uint64_t count = 0;
14 |
15 | uint8_t *addr = (uint8_t*)malloc((WORK_SIZE)*sizeof(uint8_t));
16 | memset(addr, 1, WORK_SIZE * sizeof(uint8_t));
17 | while(count != ACCESS_COUNT){
18 |
19 | for(uint16_t i = 0; i < ACCESS_SIZE; i ++){
20 | addr[i] = addr[i] + 1;
21 | }
22 |
23 |
24 | addr += STRIDE_SIZE;
25 |
26 | count++;
27 | }
28 |
29 |
30 |
31 | return 0;
32 | }
--------------------------------------------------------------------------------
/test/Synthetic_Workload/true_random:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgist-datalab/trace_generator/42d8f70135bb91b266229eb3247e20955762a2be/test/Synthetic_Workload/true_random
--------------------------------------------------------------------------------
/test/Synthetic_Workload/true_random.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define WORK_SIZE (1L << 32) //1G Bytes
7 | #define ACCESS_SIZE 64L //64 Bytes
8 | #define STRIDE_SIZE (64L*4) //64 Bytes
9 | #define ACCESS_COUNT (WORK_SIZE/STRIDE_SIZE)
10 |
11 |
12 | int main(){
13 | uint64_t count = 0;
14 |
15 | uint8_t *addr = (uint8_t*)malloc((WORK_SIZE)*sizeof(uint8_t));
16 | memset(addr, 1, WORK_SIZE * sizeof(uint8_t));
17 | while(count != ACCESS_COUNT){
18 |
19 | uint64_t index = rand()%32768 + (rand()%( WORK_SIZE/32768)) * (32768);
20 | addr[index] +=1;
21 |
22 | count++;
23 | }
24 |
25 |
26 |
27 | return 0;
28 | }
--------------------------------------------------------------------------------
/test/test_synthetic.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$EUID" -ne 0 ]
4 | then echo "Please run as root or with sudo privileges"
5 | exit
6 | fi
7 |
8 | tool_dir=$(git rev-parse --show-toplevel)
9 | run_script="${tool_dir}/run_script/run_script.sh"
10 | synth_dir="${tool_dir}/test/Synthetic_Workload"
11 |
12 | options=("indirect_delta" "true_random" "heap" "strided_latjob" "hashmap")
13 |
14 | echo "Please select a synthetic workload to test: "
15 | PS3="Input workload number: "
16 |
17 | select opt in "${options[@]}"; do
18 | case $opt in
19 | "indirect_delta")
20 | echo "You chose $opt"
21 | break
22 | ;;
23 | "true_random")
24 | echo "You chose $opt"
25 | break
26 | ;;
27 | "heap")
28 | echo "You chose $opt"
29 | break
30 | ;;
31 | "strided_latjob")
32 | echo "You chose $opt"
33 | break
34 | ;;
35 | "hashmap")
36 | echo "You chose $opt"
37 | break
38 | ;;
39 | *) echo "Invalid option $REPLY";;
40 | esac
41 | done
42 |
43 | response=""
44 | while [[ ! "$response" =~ ^([vVpP])$ ]]; do
45 | read -r -p "Get only virtual address trace or both virtual/physical address trace? [v/p] " response
46 | if [[ "$response" =~ ^([vV])$ ]]; then
47 | trace_type="virutal"
48 | elif [[ "$response" =~ ^([pP])$ ]]; then
49 | trace_type="physical"
50 | else
51 | echo "Invalid option: $response. Please enter 'v' or 'p'."
52 | fi
53 | done
54 | echo "selected trace type: $trace_type"
55 |
56 | tname="$opt"
57 | tpath="${synth_dir}/$tname"
58 |
59 | cmd="${run_script} --type $trace_type --pref --outname $tname --input $tpath"
60 |
61 | echo "\$$cmd"
62 | $cmd
63 |
--------------------------------------------------------------------------------