-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Speeding up Scaper (part one) (#116)
* Adds a profiling script. (#106) Adding a profiling script to Scaper that we can use to keep track of performance. The script generates 100 audio samples and records info about the run. * adding some requirements needed for tests and profiling, adding a profile script * updating a few variables * adding profiling script and csv for logging results * expanding details computer by profile script * adjusting script again Co-authored-by: pseeth <[email protected]> * Replacing sox.file_info calls with soundfile.info(...).duration calls (#110) * switching to soundfile for checking duration speeds things up * pysoundfile has moved to soundfile on pip, updating setup.py * install only one version of soundfile... * Using Soundfile I/O operations + build_array functions from PySox (#111) This changes the mechanisms within the `_generate_audio` function to use SoundFile for I/O and to use the build_array function from `sox` 1.4.0b0. * Switching to using "build_array" + soundfile operations. * Using soundfile ops + build_array gives a performance boost. * np.pad in python 2.7 requires mode as a positional argument. * source -> event in _generate_audio for structures holding numpy arrays * cleaning up a stray comment * adding a comment about needing both convert and set_output_format. * adding back in a line for cleaner git diff * Changing nomenclature, cleaning some stuff up. * Had a duplicate line. Fixed. * Removing context manager that was used for an easier CR. * Changing tfm.fade operation to a numpy operation. (#117) Fade operation happens directly on the numpy arrays containing the audio samples now, rather than going through sox. * Changing fade to equiv numpy op * Switching to using fade in-memory gives slightly more speed. * Fixing some multichannel bugs when switching to in-memory ops. (#118) * Fixing some multichannel bugs. * Updating the test case, sidestepping multi-channel regression data for now. * Pinning pyristent to support Python 2.7, 3.4. * Pinning jsonschema instead. * Pinning pyristent to a working version, hopefully. * pyristent -> pyrsistent *facepalm* * Fix for Issue #113, trimming with isolated events. (#115) Fixes a bug that happens when you trim an event, then generate from the trimmed JAMS file, with saving of isolated sources enabled. * Updating test for trimming soundscapes to take into account saving isolated sources * Pushing the actual fix to generate_from_jams. * Updating changelog and bumping version * Using TemporaryDirectory in the test case now, rather than relying on the whims of tempfile * Raising atol in a test from 1e-5 to 1e-4. * Adding subtype to soundfile.write to get rid of precision issues. Co-authored-by: pseeth <[email protected]> * Bumping to 1.4.0 and changing sox dependency. * Updating changelog again. * Updating profiler results. Co-authored-by: pseeth <[email protected]>
- Loading branch information
Showing
8 changed files
with
418 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
time_of_run,scaper_version,python_version,system,machine,processor,n_cpu,n_workers,memory,n_soundscapes,execution_time,git_commit_hash | ||
2020-07-17 14:13:46.982171,1.3.8,3.7.7,Darwin,x86_64,i386,8,1,16.0 GB,100,149.7468,e0c08d4f6eb10bc0b337a9d47f86b3b110ed0836 | ||
2020-07-17 14:59:33.707885,1.3.8,3.7.7,Darwin,x86_64,i386,8,1,16.0 GB,100,135.1724,c780d270b0ea0c691e1cc1dbf725d1c4b35e5299 | ||
2020-07-20 14:39:41.950552,1.3.8,3.7.7,Darwin,x86_64,i386,8,1,16.0 GB,100,118.7033,8c0cfe3c14e06bf46bcd6480f6be5991b0fba077 | ||
2020-07-21 11:04:32.178729,1.3.8,3.7.7,Darwin,x86_64,i386,8,1,16.0 GB,100,114.4563,e903933594cb86b187c6c79066f969a9653d1897 | ||
2020-09-18 16:57:39.359920,1.4.0,3.8.3,Darwin,x86_64,i386,8,1,16.0 GB,100,121.6504,d9346f71a7992e7a2578186a7ad9238d93aa3e66 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
""" | ||
This is a profiling script to check the performance of | ||
Scaper. It generates 100 soundscapes in sequence | ||
(no parallelization). Running it on 2019 Macbook Pro | ||
currently takes 158.68 seconds (02:38). | ||
""" | ||
|
||
import scaper | ||
import numpy as np | ||
import tempfile | ||
import os | ||
import tqdm | ||
import zipfile | ||
import subprocess | ||
import time | ||
import csv | ||
import platform | ||
import psutil | ||
import datetime | ||
import math | ||
import multiprocessing | ||
|
||
# Download the audio automatically | ||
FIX_DIR = 'tests/data/' | ||
|
||
def get_git_commit_hash(): | ||
process = subprocess.Popen( | ||
['git', 'rev-parse', 'HEAD'], shell=False, stdout=subprocess.PIPE) | ||
git_head_hash = process.communicate()[0].strip().decode('utf-8') | ||
return git_head_hash | ||
|
||
def convert_size(size_bytes): | ||
if size_bytes == 0: | ||
return "0B" | ||
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") | ||
i = int(math.floor(math.log(size_bytes, 1024))) | ||
p = math.pow(1024, i) | ||
s = round(size_bytes / p, 2) | ||
return "%s %s" % (s, size_name[i]) | ||
|
||
with tempfile.TemporaryDirectory() as tmpdir: | ||
path_to_audio = os.path.join(FIX_DIR, 'audio/') | ||
# OUTPUT FOLDER | ||
outfolder = tmpdir | ||
|
||
# SCAPER SETTINGS | ||
fg_folder = os.path.join(path_to_audio, 'foreground') | ||
bg_folder = os.path.join(path_to_audio, 'background') | ||
|
||
# If we parallelize this script, change this accordingly | ||
n_workers = 1 | ||
|
||
n_soundscapes = 100 | ||
ref_db = -50 | ||
duration = 10.0 | ||
|
||
min_events = 1 | ||
max_events = 9 | ||
|
||
event_time_dist = 'truncnorm' | ||
event_time_mean = 5.0 | ||
event_time_std = 2.0 | ||
event_time_min = 0.0 | ||
event_time_max = 10.0 | ||
|
||
source_time_dist = 'const' | ||
source_time = 0.0 | ||
|
||
event_duration_dist = 'uniform' | ||
event_duration_min = 0.5 | ||
event_duration_max = 4.0 | ||
|
||
snr_dist = 'uniform' | ||
snr_min = 6 | ||
snr_max = 30 | ||
|
||
pitch_dist = 'uniform' | ||
pitch_min = -3.0 | ||
pitch_max = 3.0 | ||
|
||
time_stretch_dist = 'uniform' | ||
time_stretch_min = 0.8 | ||
time_stretch_max = 1.2 | ||
|
||
# generate a random seed for this Scaper object | ||
seed = 123 | ||
|
||
# create a scaper that will be used below | ||
sc = scaper.Scaper(duration, fg_folder, bg_folder, random_state=seed) | ||
sc.protected_labels = [] | ||
sc.ref_db = ref_db | ||
|
||
# Generate 100 soundscapes using a truncated normal distribution of start times | ||
start_time = time.time() | ||
|
||
for n in tqdm.trange(n_soundscapes): | ||
print('Generating soundscape: {:d}/{:d}'.format(n+1, n_soundscapes)) | ||
|
||
# reset the event specifications for foreground and background at the | ||
# beginning of each loop to clear all previously added events | ||
sc.reset_bg_event_spec() | ||
sc.reset_fg_event_spec() | ||
|
||
# add background | ||
sc.add_background(label=('choose', []), | ||
source_file=('choose', []), | ||
source_time=('const', 0)) | ||
sc.fade_in_len = 0.01 | ||
sc.fade_out_len = 0.01 | ||
|
||
# add random number of foreground events | ||
n_events = np.random.randint(min_events, max_events+1) | ||
for _ in range(n_events): | ||
sc.add_event(label=('choose', []), | ||
source_file=('choose', []), | ||
source_time=(source_time_dist, source_time), | ||
event_time=(event_time_dist, event_time_mean, event_time_std, event_time_min, event_time_max), | ||
event_duration=(event_duration_dist, event_duration_min, event_duration_max), | ||
snr=(snr_dist, snr_min, snr_max), | ||
pitch_shift=(pitch_dist, pitch_min, pitch_max), | ||
time_stretch=(time_stretch_dist, time_stretch_min, time_stretch_max) | ||
) | ||
# generate | ||
audiofile = os.path.join(outfolder, "soundscape_unimodal{:d}.wav".format(n)) | ||
jamsfile = os.path.join(outfolder, "soundscape_unimodal{:d}.jams".format(n)) | ||
txtfile = os.path.join(outfolder, "soundscape_unimodal{:d}.txt".format(n)) | ||
|
||
sc.generate(audiofile, jamsfile, | ||
allow_repeated_label=True, | ||
allow_repeated_source=True, | ||
reverb=0.1, | ||
disable_sox_warnings=True, | ||
no_audio=False, | ||
txt_path=txtfile) | ||
|
||
time_taken = time.time() - start_time | ||
uname = platform.uname() | ||
|
||
row = { | ||
'time_of_run': str(datetime.datetime.now()), | ||
'scaper_version': scaper.__version__, | ||
'python_version': platform.python_version(), | ||
'system': uname.system, | ||
'machine': uname.machine, | ||
'processor': uname.processor, | ||
'n_cpu': multiprocessing.cpu_count(), | ||
'n_workers': n_workers, | ||
'memory': convert_size(psutil.virtual_memory().total), | ||
'n_soundscapes': n_soundscapes, | ||
'execution_time': np.round(time_taken, 4), | ||
'git_commit_hash': get_git_commit_hash(), | ||
} | ||
|
||
fieldnames = list(row.keys()) | ||
|
||
results_path = 'tests/profile_results.csv' | ||
write_header = not os.path.exists(results_path) | ||
|
||
with open(results_path, 'a') as f: | ||
writer = csv.DictWriter(f, fieldnames=fieldnames) | ||
if write_header: | ||
writer.writeheader() | ||
writer.writerow(row) | ||
|
||
with open(results_path, 'r') as f: | ||
csv_f = csv.reader(f) | ||
for row in csv_f: | ||
print('{:<30} {:<15} {:<15} {:<10} {:<10} {:<10} {:<5} {:<10} {:<10} {:<15} {:<10} {:}'.format(*row)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters