Skip to content

Instantly share code, notes, and snippets.

@ms1995
Last active March 24, 2022 22:52
Show Gist options
  • Save ms1995/515c74dcaf47a52a32ebb5a95b331db5 to your computer and use it in GitHub Desktop.
Save ms1995/515c74dcaf47a52a32ebb5a95b331db5 to your computer and use it in GitHub Desktop.
Runs each command on a single, dedicated CPU. Useful when `isolcpus` is enabled and need to run many single-threaded programs.
import os
import sys
import concurrent.futures
import threading
import subprocess
import random
# Runs each command on a single, dedicated CPU.
# Useful when `isolcpus` is enabled and need to run many single-threaded programs.
CPUS = list(range(12, 24)) + list(range(36, 48))
WORKER_THREAD_PREFIX = 'pWorker'
with open(sys.argv[1], 'r') as f:
cmds = f.readlines()
random.shuffle(cmds)
class ThreadSafeCounter():
# https://stackoverflow.com/questions/1717393/is-the-operator-thread-safe-in-python
def __init__(self):
self.lock = threading.Lock()
self.counter = 0
def increment(self):
with self.lock:
self.counter += 1
def decrement(self):
with self.lock:
self.counter -= 1
ct = ThreadSafeCounter()
def worker(cmd):
global CPUS, WORKER_THREAD_PREFIX, ct, cmds
n = threading.current_thread().name
if not n.startswith(WORKER_THREAD_PREFIX + '_'):
print('[ERROR] Thread name is not prefixed with {}'.format(
WORKER_THREAD_PREFIX))
return
n = int(n[len(WORKER_THREAD_PREFIX + '_'):])
c = CPUS[n]
print('[INFO] Running on CPU #{}: {}'.format(c, cmd))
subprocess.run(['taskset', '-c', str(c), 'bash', '-c', cmd])
ct.increment()
print('[INFO] Finished on CPU #{}, {}/{} task(s) done'.format(c,
ct.counter, len(cmds)))
executor = concurrent.futures.ThreadPoolExecutor(
max_workers=len(CPUS), thread_name_prefix=WORKER_THREAD_PREFIX)
for i, cmd in enumerate(cmds):
# print('[INFO] Submitting command #{}, total {}'.format(i + 1, len(cmds)))
executor.submit(worker, cmd.strip())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment