Skip to content

Commit

Permalink
Merge pull request #54 from powergee/master
Browse files Browse the repository at this point in the history
Add HP with Optimistic Traversal
  • Loading branch information
tomtomjhj authored Nov 28, 2024
2 parents f46a5ec + 7401573 commit 92e0dad
Show file tree
Hide file tree
Showing 100 changed files with 12,058 additions and 812 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ tags
*.pdf
*.csv
.python-version
__pycache__
21 changes: 11 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ csv = "1.3.0"
rand = "0.8"
typenum = "1.17"
num = "0.4.3"
arrayvec = "0.7.6"
scopeguard = "1"
hp_pp = { path = "./smrs/hp-pp" }
nbr = { path = "./smrs/nbr" }
cdrc = { path = "./smrs/cdrc" }
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ where
* `skip-list`: lock-free skiplist by Herlihy and Shavit, with wait-free get() for schemes other than HP \[3\]
* `bonsai-tree`: A non-blocking variant of Bonsai tree \[5\]
* `efrb-tree`: Ellen et al. ’s tree \[6\]
* `elim-ab-tree`: An (a,b) tree with elimination \[17\]
* Reclamation scheme
* `nr`: A baseline that does not reclaim memory
* `ebr`: Epoch-based RCU \[1,7\]
Expand Down Expand Up @@ -276,3 +277,4 @@ Note that sanitizer may report memory leaks when used against CIRC EBR. This is
* \[14\] Jeonghyeon Kim, Jaehwang Jung, and Jeehoon Kang. 2024. Expediting Hazard Pointers with Bounded RCU Critical Sections. In Proceedings of the 36th ACM Symposium on Parallelism in Algorithms and Architectures (SPAA 2024), June 17–21, 2024, Nantes, France. ACM, New York, NY, USA, 34 pages. <https://doi.org/10.1145/3626183.3659941>
* \[15\] Jaehwang Jung, Jeonghyeon Kim, Matthew J. Parkinson, and Jeehoon Kang. 2024. Concurrent Immediate Reference Counting. Proc. ACM Program. Lang. 8, PLDI, Article 153 (June 2024), 24 pages. <https://doi.org/10.1145/3656383>
* \[16\] Gali Sheffi, Maurice Herlihy, and Erez Petrank. 2021. VBR: Version Based Reclamation. In Proceedings of the 33rd ACM Symposium on Parallelism in Algorithms and Architectures (Virtual Event, USA) (SPAA ’21). Association for Computing Machinery, New York, NY, USA, 443–445. <https://doi.org/10.1145/3409964.3461817>
* \[17\] Anubhav Srivastava and Trevor Brown. 2022. Elimination (a,b)-trees with fast, durable updates. In Proceedings of the 27th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming (PPoPP '22). Association for Computing Machinery, New York, NY, USA, 416–430. <https://doi.org/10.1145/3503221.3508441>
99 changes: 99 additions & 0 deletions bench-scripts/hp-revisited/bench-hp-trees.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python

import subprocess
import os

RESULTS_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "results")
BIN_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..", "target", "release")

dss = ['nm-tree', 'efrb-tree']
# "-large" suffix if it uses a large garbage bag.
mms = ['hp']
i = 10
cpu_count = os.cpu_count()
if not cpu_count or cpu_count <= 24:
ts = list(map(str, [1] + list(range(4, 33, 4))))
elif cpu_count <= 64:
ts = list(map(str, [1] + list(range(8, 129, 8))))
else:
ts = list(map(str, [1] + list(range(12, 193, 12))))
runs = 2
gs = [0, 1, 2]

subprocess.run(['cargo', 'build', '--release'])

def key_ranges(ds):
return ["100000"]

def is_suffix(orig, suf):
return len(suf) <= len(orig) and mm[-len(suf):] == suf

def make_cmd(mm, i, ds, g, t, kr):
bag = "small"
if is_suffix(mm, "-large"):
mm = mm[:len(mm)-len("-large")]
bag = "large"

return [os.path.join(BIN_PATH, mm),
'-i', str(i),
'-d', str(ds),
'-g', str(g),
'-t', str(t),
'-r', str(kr),
'-b', bag,
'-o', os.path.join(RESULTS_PATH, f'{ds}.csv')]

def invalid(mm, ds, g):
is_invalid = False
if ds == 'hhs-list':
is_invalid |= g == 0 # HHSList is just HList with faster get()
if mm == 'nbr':
is_invalid |= ds in ["hm-list", "skip-list"]
if ds == 'elim-ab-tree':
is_invalid |= mm in ["pebr", "hp-pp", "vbr"]
return is_invalid

cmds = []

for ds in dss:
for kr in key_ranges(ds):
for mm in mms:
for g in gs:
if invalid(mm, ds, g):
continue
for t in ts:
cmds.append(make_cmd(mm, i, ds, g, t, kr))

print('number of configurations: ', len(cmds))
print('estimated time: ', (len(cmds) * i * 1.1) // 60, ' min *', runs, 'times\n')

for i, cmd in enumerate(cmds):
try:
print(f"\rdry-running commands... ({i+1}/{len(cmds)})", end="")
subprocess.run(cmd + ['--dry-run'])
except:
print(f"A dry-run for the following command is failed:\n{' '.join(cmd)}")
exit(1)
print("\nAll dry-runs passed!\n")

os.makedirs(RESULTS_PATH, exist_ok=True)
failed = []
for run in range(runs):
for i, cmd in enumerate(cmds):
print("run {}/{}, bench {}/{}: '{}'".format(run + 1, runs, i + 1, len(cmds), ' '.join(cmd)))
try:
subprocess.run(cmd, timeout=i+30)
except subprocess.TimeoutExpired:
print("timeout")
failed.append(' '.join(cmd))
except KeyboardInterrupt:
if len(failed) > 0:
print("====failed====")
print("\n".join(failed))
exit(0)
except:
failed.append(' '.join(cmd))

if len(failed) > 0:
print("====failed====")
print("\n".join(failed))
99 changes: 99 additions & 0 deletions bench-scripts/hp-revisited/bench-short-lists.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python

import subprocess
import os

RESULTS_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "results")
BIN_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..", "target", "release")

dss = ['hhs-list', 'hm-list']
# "-large" suffix if it uses a large garbage bag.
mms = ['hp', 'hp-pp']
i = 10
cpu_count = os.cpu_count()
if not cpu_count or cpu_count <= 24:
ts = list(map(str, [1] + list(range(4, 33, 4))))
elif cpu_count <= 64:
ts = list(map(str, [1] + list(range(8, 129, 8))))
else:
ts = list(map(str, [1] + list(range(12, 193, 12))))
runs = 2
gs = [0, 1, 2]

subprocess.run(['cargo', 'build', '--release'])

def key_ranges(ds):
return ["16"]

def is_suffix(orig, suf):
return len(suf) <= len(orig) and mm[-len(suf):] == suf

def make_cmd(mm, i, ds, g, t, kr):
bag = "small"
if is_suffix(mm, "-large"):
mm = mm[:len(mm)-len("-large")]
bag = "large"

return [os.path.join(BIN_PATH, mm),
'-i', str(i),
'-d', str(ds),
'-g', str(g),
'-t', str(t),
'-r', str(kr),
'-b', bag,
'-o', os.path.join(RESULTS_PATH, f'{ds}.csv')]

def invalid(mm, ds, g):
is_invalid = False
if ds == 'hhs-list':
is_invalid |= g == 0 # HHSList is just HList with faster get()
if mm == 'nbr':
is_invalid |= ds in ["hm-list", "skip-list"]
if ds == 'elim-ab-tree':
is_invalid |= mm in ["pebr", "hp-pp", "vbr"]
return is_invalid

cmds = []

for ds in dss:
for kr in key_ranges(ds):
for mm in mms:
for g in gs:
if invalid(mm, ds, g):
continue
for t in ts:
cmds.append(make_cmd(mm, i, ds, g, t, kr))

print('number of configurations: ', len(cmds))
print('estimated time: ', (len(cmds) * i * 1.1) // 60, ' min *', runs, 'times\n')

for i, cmd in enumerate(cmds):
try:
print(f"\rdry-running commands... ({i+1}/{len(cmds)})", end="")
subprocess.run(cmd + ['--dry-run'])
except:
print(f"A dry-run for the following command is failed:\n{' '.join(cmd)}")
exit(1)
print("\nAll dry-runs passed!\n")

os.makedirs(RESULTS_PATH, exist_ok=True)
failed = []
for run in range(runs):
for i, cmd in enumerate(cmds):
print("run {}/{}, bench {}/{}: '{}'".format(run + 1, runs, i + 1, len(cmds), ' '.join(cmd)))
try:
subprocess.run(cmd, timeout=i+30)
except subprocess.TimeoutExpired:
print("timeout")
failed.append(' '.join(cmd))
except KeyboardInterrupt:
if len(failed) > 0:
print("====failed====")
print("\n".join(failed))
exit(0)
except:
failed.append(' '.join(cmd))

if len(failed) > 0:
print("====failed====")
print("\n".join(failed))
Loading

0 comments on commit 92e0dad

Please sign in to comment.