Skip to content

Commit 9db17fc

Browse files
committedJun 21, 2019
add benchmark.py and clean receiver a bit
1 parent 019d063 commit 9db17fc

File tree

4 files changed

+244
-22
lines changed

4 files changed

+244
-22
lines changed
 

‎Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ TARGETS=sender receiver sender_debug receiver_debug
66
UTILS=util.o
77

88
all: $(TARGETS) $(DEBUGTARGETS)
9+
cp sender pp-llc-send
10+
cp receiver pp-llc-recv
911

1012
%.o: %.c
1113
$(CC) $(CFLAGS) -c $<

‎benchmark.py

+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#! /usr/bin/env /usr/bin/python3
2+
3+
import subprocess
4+
from time import sleep
5+
import shutil
6+
import os
7+
import numpy
8+
import json
9+
10+
class channel_benchmark():
11+
def __init__(self, tests, runsPerTest=10, timeBetweenRuns=1,
12+
senderCore=0, readerCore=2,
13+
channelArgs=["interval", "primeTime", "accessTime"]):
14+
15+
self.sender = ['taskset', '-c', str(senderCore),
16+
sender_bin, "-b"]
17+
print(self.sender)
18+
self.resultFile = os.path.join(result_dir, "llc-pp.json")
19+
try:
20+
os.mkdir(result_dir)
21+
except (OSError):
22+
pass
23+
24+
self.reader = ['taskset', '-c', str(readerCore),
25+
reader_bin, "-b"]
26+
27+
self.cool_down = timeBetweenRuns
28+
self.channelArgs = channelArgs
29+
self.runs = runsPerTest
30+
self.tests = tests
31+
32+
def readChannelFile(self, f):
33+
if os.path.isfile(f):
34+
with open(f) as fd:
35+
return [int(datum.split(" ")[1]) for datum in fd.readlines()]
36+
else:
37+
return []
38+
39+
def check(self, sender, reader):
40+
readerData = self.readChannelFile(reader)
41+
senderData = self.readChannelFile(sender)
42+
transition = numpy.zeros((2, 2), dtype=numpy.float64)
43+
if (len(senderData) != len(readerData)) :
44+
print("Data length mismatch!")
45+
elif (len(senderData) == 0) :
46+
print("No Data!")
47+
else:
48+
for sent,read in zip(senderData, readerData):
49+
transition[sent, read] += 1
50+
print("Printing bit transition matrix as:")
51+
print("[[0 -> 0, 0 -> 1],\n [1 -> 0, 0 -> 1]]\n")
52+
print(transition)
53+
return transition
54+
55+
def capacity(self, transition):
56+
m,n = transition.shape
57+
r = numpy.ones((m,)) / m
58+
q = numpy.zeros((m,n))
59+
error_allowed = 1e-5/m
60+
for i in range(n):
61+
if transition[:,i].sum() == 0:
62+
print("error: transition matrix contains a zero columnn")
63+
return 0
64+
65+
for i in range(m):
66+
if transition[i].sum() == 0:
67+
print("error: transition matrix contains a zero row")
68+
return 0
69+
transition[i] /= transition[i].sum()
70+
71+
for iter in range(10000):
72+
for i in range(n):
73+
q[:,i] = r * transition[:,i]
74+
q[:,i] /= q[:,i].sum()
75+
rprime = r.copy()
76+
for i in range(m):
77+
rprime[i] = (q[i]**transition[i]).prod()
78+
rprime = rprime/rprime.sum()
79+
if (numpy.linalg.norm(rprime - r)) < error_allowed:
80+
break
81+
else:
82+
r = rprime
83+
84+
cap = 0
85+
for i in range(m):
86+
for j in range(n):
87+
if (r[i] > 0 and q[i,j] > 0):
88+
cap += r[i]*transition[i,j]*numpy.log2(q[i,j]/r[i])
89+
return cap
90+
91+
92+
def doTest(self, paramMap):
93+
print("\n==== Test parameters:{} ====".format(paramMap))
94+
try:
95+
shutil.rmtree(data_dir)
96+
except (OSError):
97+
pass
98+
try:
99+
os.mkdir(data_dir)
100+
except (OSError):
101+
pass
102+
contents = {}
103+
if not os.path.isfile(self.resultFile) \
104+
or os.path.getmtime(sender_bin) < os.path.getmtime(self.resultFile):
105+
try:
106+
with open(self.resultFile) as results:
107+
contents = json.load(results)
108+
except OSError:
109+
pass
110+
except Exception:
111+
print("Warning: corrupted results file")
112+
113+
key = json.dumps([paramMap[arg] for arg in self.channelArgs])
114+
if (key in contents) and (len(contents[key]) >= 3):
115+
# estimate
116+
bitsPerSec = 2300 * 1000 * 1000 / paramMap["interval"]
117+
print(" Capacity: {}".format(max(contents[key])))
118+
print(" Bandwidth: {}".format(max(contents[key]) * bitsPerSec))
119+
return max(contents[key]) * bitsPerSec
120+
121+
for i in range(self.runs):
122+
print(" run #{}...".format(i), end='')
123+
readerOut = os.path.join(data_dir, "receiverSave")
124+
senderOut = os.path.join(data_dir, "senderSave")
125+
reader = subprocess.Popen(self.reader
126+
+ ['-i', str(paramMap['interval'])]
127+
+ ['-p', str(paramMap['primeTime'])]
128+
+ ['-a', str(paramMap['accessTime'])]
129+
,stdin=subprocess.PIPE
130+
,stdout=subprocess.PIPE
131+
# ,cwd=run_dir
132+
,env=env)
133+
sender = subprocess.Popen(self.sender
134+
+ ['-i', str(paramMap['interval'])]
135+
+ ['-p', str(paramMap['primeTime'])]
136+
+ ['-a', str(paramMap['accessTime'])]
137+
,stdin=subprocess.PIPE
138+
,stdout=subprocess.PIPE
139+
# ,cwd=run_dir
140+
,env=env)
141+
sleep(self.cool_down)
142+
sender.wait()
143+
sleep(self.cool_down)
144+
# reader.wait() # needs work
145+
# in case reader did not get all rounds of testing from sender
146+
if reader.poll is None:
147+
reader.kill()
148+
print("Reader faild to get all benchmarking messages\n");
149+
return 0
150+
print("Done")
151+
152+
reader_stdout = reader.communicate()[0].decode().split(' ')
153+
bits = int(reader_stdout[-4])
154+
nsec = int(reader_stdout[-1])
155+
156+
if paramMap["interval"] != 0:
157+
# bitsPerSec_no_sync = 2300 * 1000 * 1000 / paramMap["interval"]
158+
bitsPerSec = bits * 1e9 / nsec
159+
else:
160+
eitsPerSec = 0
161+
162+
if (key not in contents) :
163+
contents[key] = []
164+
cap = float(self.capacity(self.check(senderOut, readerOut)))
165+
print(" Capacity: {}".format(cap))
166+
print(" Bandwidth: {}".format(cap * bitsPerSec))
167+
contents[key] += [cap]
168+
with open(self.resultFile, "w+") as results:
169+
json.dump(contents,results)
170+
results.flush()
171+
return max(contents[key]) * bitsPerSec
172+
173+
def benchmark(self):
174+
for test in self.tests:
175+
self.doTest(test)
176+
177+
if __name__ == '__main__':
178+
data = map(
179+
lambda s: {"interval":s[0], "primeTime":s[1], "accessTime":s[2]},
180+
[# interval, primeTime, accessTime
181+
(2000000, 800000, 800000),
182+
(1000000, 400000, 400000)
183+
][0:2])
184+
185+
base_dir = os.path.dirname(os.path.abspath(__file__))
186+
print(base_dir)
187+
data_dir = os.path.join(base_dir , "data")
188+
result_dir = os.path.join(base_dir, "llc-results")
189+
190+
sender_bin = os.path.join(base_dir, "pp-llc-send")
191+
reader_bin = os.path.join(base_dir, "pp-llc-recv")
192+
193+
if not os.path.isfile(sender_bin) or not os.path.isfile(reader_bin):
194+
print("Please have this script in the same folder as the executables")
195+
exit()
196+
197+
env = os.environ.copy()
198+
try :
199+
env["LD_LIBRARY_PATH"] += ":" + base_dir
200+
except KeyError:
201+
env["LD_LIBRARY_PATH"] = base_dir
202+
203+
channel = channel_benchmark(data
204+
,runsPerTest=1
205+
,readerCore=0
206+
,senderCore=2)
207+
channel.benchmark();
208+

‎receiver.c

+27-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/*
44
* Parses the arguments and flags of the program and initializes the struct config
5-
* with those parameters (or the default ones if no custom flags are given).
5+
* with those parameters (or the default ones if no custom flags are given).
66
*/
77
void init_config(struct config *config, int argc, char **argv) {
88
uint64_t pid = print_pid();
@@ -70,9 +70,9 @@ void init_config(struct config *config, int argc, char **argv) {
7070
}
7171

7272
// receiver function pointer
73-
bool (*detect_bit)(const struct config*, bool);
73+
bool (*detect_bit)(const struct config*);
7474

75-
bool detect_bit_fr(const struct config *config, bool first_time) {
75+
bool detect_bit_fr(const struct config *config) {
7676
int misses = 0;
7777
int hits = 0;
7878
int total_measurements = 0;
@@ -117,8 +117,8 @@ bool detect_bit_fr(const struct config *config, bool first_time) {
117117
* If the the first_bit argument is true, relax the strict definition of "one" and try to
118118
* cc_sync with the sender.
119119
*/
120-
// bool detect_bit(const struct config *config, bool first_bit, uint64_t start_t)
121-
bool detect_bit_pp(const struct config *config, bool first_bit)
120+
// bool detect_bit(const struct config *config, uint64_t start_t)
121+
bool detect_bit_pp(const struct config *config)
122122
{
123123
uint64_t start_t = get_time();
124124
// debug("time %lx\n", start_t);
@@ -189,43 +189,52 @@ bool detect_bit_pp(const struct config *config, bool first_bit)
189189
// static const int MAX_BUFFER_LEN = 128 * 8;
190190

191191
void benchmark_receive(struct config *config_p) {
192+
FILE *receiverSave = fopen("data/receiverSave", "w+");
193+
if (receiverSave == NULL) {
194+
fprintf(stderr, "ERROR: cannot open file to save.\n"
195+
"Check if data/ folder is created\n");
196+
exit(-1);
197+
}
198+
192199
uint32_t benchmarkSize = 8192;
193200
uint8_t *msg = (uint8_t *)malloc(sizeof(uint8_t) * benchmarkSize);
194-
uint64_t start_t, bench_start_t = 0, bench_end_t = 0;
201+
uint64_t start_t;
202+
struct timespec beg_t, end_t;
195203
for (uint32_t i = 0; i < benchmarkSize; i++) {
196204
// sync every 1024 bits, detecting pilot signal again
197205
if ((i & 0x3ff) == 0) {
198206
bool curr = true, prev = true;
199207
int flip_sequence = 4;
200208
while (true) {
201209
start_t = cc_sync();
202-
curr = detect_bit(config_p, true);
210+
curr = detect_bit(config_p);
203211

204212
if (flip_sequence == 0 && curr == 1 && prev == 1) {
205213
debug("pilot signal detected for round %u\r", i / 1024);
206214
start_t = cc_sync();
207-
bench_start_t = i == 0? start_t: bench_start_t;
215+
if (i == 0) clock_gettime(CLOCK_MONOTONIC, &beg_t);
208216
break;
209217
}
210218
else if (flip_sequence > 0 && curr != prev) {
211219
flip_sequence--;
212220
}
213-
else if (curr == prev) {
221+
else if (curr == prev) {
214222
flip_sequence = 4;
215223
}
216224
prev = curr;
217225
}
218226
}
219227

220-
msg[i] = detect_bit(config_p, true);
228+
msg[i] = detect_bit(config_p);
221229

222230
}
223-
bench_end_t = get_time();
231+
232+
clock_gettime(CLOCK_MONOTONIC, &end_t);
224233
printf("total cycles to receive %u bits is %lu\n", benchmarkSize,
225-
bench_end_t - bench_start_t);
234+
(end_t.tv_sec - beg_t.tv_sec) * (long)1e9 + (end_t.tv_nsec -
235+
beg_t.tv_nsec));
226236

227237
if (msg) {
228-
FILE *receiverSave = fopen("receiverSave", "w+");
229238
for (uint32_t i = 0; i < benchmarkSize; i++) {
230239
fprintf(receiverSave, "%u %u\n", i, msg[i]);
231240
}
@@ -250,7 +259,6 @@ int main(int argc, char **argv)
250259

251260
char msg_ch[MAX_BUFFER_LEN + 1];
252261
int flip_sequence = 4;
253-
bool first_time = true;
254262
bool current;
255263
bool previous = true;
256264

@@ -265,8 +273,8 @@ int main(int argc, char **argv)
265273

266274
// cc_sync on clock edge
267275
uint64_t start_t = cc_sync();
268-
// current = detect_bit(&config, first_time, start_t);
269-
current = detect_bit(&config, first_time);
276+
// current = detect_bit(&config, start_t);
277+
current = detect_bit(&config);
270278

271279
// This receiving loop is a sort of finite config machine.
272280
// Once again, it would be easier to explain how it works
@@ -298,8 +306,8 @@ int main(int argc, char **argv)
298306
start_t = cc_sync();
299307
for (msg_len = 0; msg_len < MAX_BUFFER_LEN; msg_len++) {
300308
#if 1
301-
// uint32_t bit = detect_bit(&config, first_time, start_t);
302-
uint32_t bit = detect_bit(&config, first_time);
309+
// uint32_t bit = detect_bit(&config, start_t);
310+
uint32_t bit = detect_bit(&config);
303311
msg_ch[msg_len] = '0' + bit;
304312
strike_zeros = (strike_zeros + (1-bit)) & (bit-1);
305313
if (strike_zeros >= 8 && ((msg_len & 0x7) == 0)) {
@@ -308,7 +316,7 @@ int main(int argc, char **argv)
308316
}
309317

310318
#else
311-
if (detect_bit(&config, first_time)) {
319+
if (detect_bit(&config)) {
312320
msg_ch[msg_len] = '1';
313321
strike_zeros = 0;
314322
} else {
@@ -334,11 +342,9 @@ int main(int argc, char **argv)
334342

335343
} else if (flip_sequence > 0 && current != previous) {
336344
flip_sequence--;
337-
first_time = false;
338345

339346
} else if (current == previous) {
340347
flip_sequence = 4;
341-
first_time = true;
342348
}
343349

344350
previous = current;

‎sender.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ uint8_t *generate_random_msg(uint32_t size) {
167167
}
168168

169169
void benchmark_send(struct config *config_p) {
170+
FILE *senderSave = fopen("data/senderSave", "w+");
171+
if (!senderSave) {
172+
fprintf(stderr, "ERROR: cannot open file to save.\n"
173+
"Check if data/ folder is created\n");
174+
exit(-1);
175+
}
176+
170177
uint32_t benchmarkSize = 8192;
171178
uint8_t *randomMsg = generate_random_msg(benchmarkSize);
172179
uint64_t start_t;
@@ -193,7 +200,6 @@ void benchmark_send(struct config *config_p) {
193200
}
194201

195202
if (randomMsg) {
196-
FILE *senderSave = fopen("senderSave", "w+");
197203
for (uint32_t i = 0; i < benchmarkSize; i++) {
198204
fprintf(senderSave, "%u %u\n", i, randomMsg[i]);
199205
}

0 commit comments

Comments
 (0)
Please sign in to comment.