omniopt2 8178__py3-none-any.whl → 9171__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. .gitignore +2 -0
  2. .helpers.py +0 -9
  3. .omniopt.py +1717 -1151
  4. .omniopt_plot_scatter.py +1 -1
  5. .omniopt_plot_scatter_hex.py +1 -1
  6. .omniopt_plot_trial_index_result.py +1 -0
  7. .pareto.py +134 -0
  8. .shellscript_functions +24 -15
  9. .tests/pylint.rc +0 -4
  10. .tpe.py +4 -3
  11. README.md +1 -1
  12. omniopt +92 -55
  13. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.helpers.py +0 -9
  14. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt.py +1717 -1151
  15. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_scatter.py +1 -1
  16. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_scatter_hex.py +1 -1
  17. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_trial_index_result.py +1 -0
  18. omniopt2-9171.data/data/bin/.pareto.py +134 -0
  19. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.shellscript_functions +24 -15
  20. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.tpe.py +4 -3
  21. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/omniopt +92 -55
  22. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/omniopt_docker +60 -60
  23. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/omniopt_plot +1 -1
  24. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/pylint.rc +0 -4
  25. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/requirements.txt +3 -4
  26. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/test_requirements.txt +1 -0
  27. {omniopt2-8178.dist-info → omniopt2-9171.dist-info}/METADATA +6 -6
  28. omniopt2-9171.dist-info/RECORD +73 -0
  29. omniopt2.egg-info/PKG-INFO +6 -6
  30. omniopt2.egg-info/SOURCES.txt +1 -0
  31. omniopt2.egg-info/requires.txt +4 -4
  32. omniopt_docker +60 -60
  33. omniopt_plot +1 -1
  34. pyproject.toml +1 -1
  35. requirements.txt +3 -4
  36. test_requirements.txt +1 -0
  37. omniopt2-8178.dist-info/RECORD +0 -71
  38. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.colorfunctions.sh +0 -0
  39. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.general.sh +0 -0
  40. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_cpu_ram_usage.py +0 -0
  41. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_general.py +0 -0
  42. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_gpu_usage.py +0 -0
  43. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_kde.py +0 -0
  44. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_scatter_generation_method.py +0 -0
  45. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_time_and_exit_code.py +0 -0
  46. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.omniopt_plot_worker.py +0 -0
  47. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/.random_generator.py +0 -0
  48. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/LICENSE +0 -0
  49. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/apt-dependencies.txt +0 -0
  50. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/omniopt_evaluate +0 -0
  51. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/omniopt_share +0 -0
  52. {omniopt2-8178.data → omniopt2-9171.data}/data/bin/setup.py +0 -0
  53. {omniopt2-8178.dist-info → omniopt2-9171.dist-info}/WHEEL +0 -0
  54. {omniopt2-8178.dist-info → omniopt2-9171.dist-info}/licenses/LICENSE +0 -0
  55. {omniopt2-8178.dist-info → omniopt2-9171.dist-info}/top_level.txt +0 -0
@@ -79,7 +79,7 @@ if ORIGINAL_PWD:
79
79
  os.chdir(ORIGINAL_PWD)
80
80
 
81
81
  @beartype
82
- def set_title(df_filtered: pd.DataFrame, result_column_values: pd.core.series.Series, num_entries: int, _min: Union[int, float, None], _max: Union[int, float, None]) -> None:
82
+ def set_title(df_filtered: pd.DataFrame, result_column_values: pd.Series, num_entries: int, _min: Union[int, float, None], _max: Union[int, float, None]) -> None:
83
83
  title = helpers.get_title(args, result_column_values, df_filtered, num_entries, _min, _max)
84
84
 
85
85
  if fig:
@@ -93,7 +93,7 @@ if ORIGINAL_PWD:
93
93
  os.chdir(ORIGINAL_PWD)
94
94
 
95
95
  @beartype
96
- def set_title(df_filtered: pd.DataFrame, result_column_values: pd.core.series.Series, num_entries: int, _min: Union[float, int, None] = None, _max: Union[float, int, None] = None) -> None:
96
+ def set_title(df_filtered: pd.DataFrame, result_column_values: pd.Series, num_entries: int, _min: Union[float, int, None] = None, _max: Union[float, int, None] = None) -> None:
97
97
  title = helpers.get_title(args, result_column_values, df_filtered, num_entries, _min, _max)
98
98
 
99
99
  if fig:
@@ -118,6 +118,7 @@ if __name__ == "__main__":
118
118
 
119
119
  if not os.path.exists(args.run_dir):
120
120
  logging.error("Specified --run_dir does not exist")
121
+
121
122
  sys.exit(1)
122
123
 
123
124
  update_graph()
@@ -0,0 +1,134 @@
1
+ import os
2
+ import importlib.util
3
+ from typing import Tuple, List, Dict, Any
4
+ from rich.table import Table
5
+ from rich.text import Text
6
+ import numpy as np
7
+
8
+
9
+ # ----------------- Helpers import -----------------
10
+ script_dir = os.path.dirname(os.path.realpath(__file__))
11
+ helpers_file: str = f"{script_dir}/.helpers.py"
12
+ spec = importlib.util.spec_from_file_location(
13
+ name="helpers",
14
+ location=helpers_file,
15
+ )
16
+ if spec is not None and spec.loader is not None:
17
+ helpers = importlib.util.module_from_spec(spec)
18
+ spec.loader.exec_module(helpers)
19
+ else:
20
+ raise ImportError(f"Could not load module from {helpers_file}")
21
+
22
+ # ----------------- Table utilities -----------------
23
+ def pareto_front_table_filter_rows(rows: List[Dict[str, str]], idxs: List[int]) -> List[Dict[str, str]]:
24
+ result = []
25
+ for row in rows:
26
+ try:
27
+ trial_index = int(row["trial_index"])
28
+ except (KeyError, ValueError):
29
+ continue
30
+
31
+ if row.get("trial_status", "").strip().upper() == "COMPLETED" and trial_index in idxs:
32
+ result.append(row)
33
+ return result
34
+
35
+ def pareto_front_table_add_headers(table: Table, param_cols: List[str], result_cols: List[str]) -> None:
36
+ for col in param_cols:
37
+ table.add_column(col, justify="center")
38
+ for col in result_cols:
39
+ table.add_column(Text(f"{col}", style="cyan"), justify="center")
40
+
41
+ def pareto_front_table_add_rows(table: Table, rows: List[Dict[str, str]], param_cols: List[str], result_cols: List[str]) -> None:
42
+ for row in rows:
43
+ values = [str(helpers.to_int_when_possible(row[col])) for col in param_cols]
44
+ result_values = [Text(str(helpers.to_int_when_possible(row[col])), style="cyan") for col in result_cols]
45
+ table.add_row(*values, *result_values, style="bold green")
46
+
47
+ # ----------------- Pareto internal utilities -----------------
48
+ def _validate_xy(x: np.ndarray, y: np.ndarray) -> None:
49
+ if x.shape != y.shape:
50
+ raise ValueError("Input arrays x and y must have the same shape.")
51
+ if x.size == 0:
52
+ raise ValueError("Input arrays must not be empty.")
53
+ if not np.isfinite(x).all() or not np.isfinite(y).all():
54
+ raise ValueError("Input arrays must contain only finite numbers (no NaN/Inf).")
55
+
56
+ def _point_dominates(xi: float, yi: float, xj: float, yj: float, x_minimize: bool, y_minimize: bool) -> bool:
57
+ """Return True if j dominates i (standard weak Pareto: >= in all, > in at least one)."""
58
+ if x_minimize:
59
+ x_better_eq = xj <= xi
60
+ x_strict = xj < xi
61
+ else:
62
+ x_better_eq = xj >= xi
63
+ x_strict = xj > xi
64
+
65
+ if y_minimize:
66
+ y_better_eq = yj <= yi
67
+ y_strict = yj < yi
68
+ else:
69
+ y_better_eq = yj >= yi
70
+ y_strict = yj > yi
71
+
72
+ return x_better_eq and y_better_eq and (x_strict or y_strict)
73
+
74
+ def _find_dominated(x: np.ndarray, y: np.ndarray, x_minimize: bool, y_minimize: bool) -> np.ndarray:
75
+ n = len(x)
76
+ is_dominated = np.zeros(n, dtype=bool)
77
+ for i in range(n):
78
+ if is_dominated[i]:
79
+ continue
80
+ xi, yi = x[i], y[i]
81
+ for j in range(n):
82
+ if i == j:
83
+ continue
84
+ xj, yj = x[j], y[j]
85
+ if _point_dominates(xi, yi, xj, yj, x_minimize, y_minimize):
86
+ is_dominated[i] = True
87
+ break
88
+ return is_dominated
89
+
90
+ # ----------------- Public Pareto functions -----------------
91
+ def pareto_front_general(
92
+ x: np.ndarray,
93
+ y: np.ndarray,
94
+ x_minimize: bool = True,
95
+ y_minimize: bool = True
96
+ ) -> np.ndarray:
97
+ try:
98
+ xa = np.asarray(x, dtype=float).ravel()
99
+ ya = np.asarray(y, dtype=float).ravel()
100
+ _validate_xy(xa, ya)
101
+ is_dominated = _find_dominated(xa, ya, x_minimize, y_minimize)
102
+ return np.where(~is_dominated)[0]
103
+ except Exception as e:
104
+ print("Error in pareto_front_general:", str(e))
105
+ return np.array([], dtype=int)
106
+
107
+ def pareto_front_filter_complete_points(
108
+ path_to_calculate: str,
109
+ records: Dict[Tuple[int, str], Dict[str, Dict[str, float]]],
110
+ primary_name: str,
111
+ secondary_name: str
112
+ ) -> List[Tuple[Tuple[int, str], float, float]]:
113
+ points = []
114
+ for key, metrics in records.items():
115
+ means = metrics['means']
116
+ if primary_name in means and secondary_name in means:
117
+ points.append((key, means[primary_name], means[secondary_name]))
118
+ if len(points) == 0:
119
+ raise ValueError(f"No full data points with both objectives found in {path_to_calculate}.")
120
+ return points
121
+
122
+ def pareto_front_select_pareto_points(
123
+ x: np.ndarray,
124
+ y: np.ndarray,
125
+ x_minimize: bool,
126
+ y_minimize: bool,
127
+ points: List[Tuple[Any, float, float]],
128
+ num_points: int
129
+ ) -> List[Tuple[Any, float, float]]:
130
+ indices = pareto_front_general(x, y, x_minimize, y_minimize)
131
+ # Sort by x ascending
132
+ sorted_indices = indices[np.argsort(x[indices])]
133
+ selected_points = [points[i] for i in sorted_indices[:num_points]]
134
+ return selected_points
@@ -207,13 +207,14 @@
207
207
  bar="${bar} "
208
208
  done
209
209
 
210
- printf "[%s] %d%% \n" "$bar" "$percentage"
210
+ printf "[%s] \n" "$bar"
211
211
  }
212
212
 
213
213
  function ppip {
214
214
  MODULE=$1
215
215
  AS_REQUIREMENT_OF=$2
216
216
  NUMBER_OF_MAIN_MODULES=$3
217
+ STR=$4
217
218
 
218
219
  set +e
219
220
 
@@ -222,7 +223,7 @@
222
223
  PROGRESSBAR=$(generate_progress_bar_setup "$NUMBER_OF_MAIN_MODULES")
223
224
 
224
225
  if [[ -z $CI ]]; then
225
- green_reset_line "${PROGRESSBAR}Installing $MODULE "
226
+ green_reset_line "${PROGRESSBAR}➤${STR}Installing $MODULE "
226
227
  fi
227
228
 
228
229
 
@@ -235,10 +236,10 @@
235
236
  if [[ "$MODULE" != "$AS_REQUIREMENT_OF" ]] && [[ "$AS_REQUIREMENT_OF" != "-" ]]; then
236
237
  k=0
237
238
 
238
- for i in $(pip3 install --disable-pip-version-check --dry-run "$MODULE" | grep -v "already satisfied" | grep "Collecting" | sed -e 's#Collecting ##' | grep -v "^$MODULE$"); do
239
+ for i in $(pip3 install --default-timeout=300 --default-timeout=300 --disable-pip-version-check --dry-run "$MODULE" | grep -v "already satisfied" | grep "Collecting" | sed -e 's#Collecting ##' | grep -v "^$MODULE$"); do
239
240
  if [[ "$i" != "$MODULE" ]]; then
240
241
  if [[ $k -eq 0 ]]; then
241
- green_reset_line "${PROGRESSBAR}Installing requirements for $MODULE"
242
+ green_reset_line "${PROGRESSBAR}➤${STR}Installing requirements for $MODULE"
242
243
  fi
243
244
  ppip "$i" "$MODULE" "$NUMBER_OF_MAIN_MODULES" || {
244
245
  red_reset_line "❌Failed to install $i."
@@ -251,11 +252,11 @@
251
252
  done
252
253
 
253
254
  if [[ $k -gt 0 ]]; then
254
- green_reset_line "${PROGRESSBAR}Installed all requirements for $MODULE, now installing the package itself..."
255
+ green_reset_line "${PROGRESSBAR}➤${STR}Installed all requirements for $MODULE, now installing the package itself..."
255
256
  fi
256
257
  fi
257
258
 
258
- green_reset_line "${PROGRESSBAR}Installing $MODULE..."
259
+ green_reset_line "${PROGRESSBAR}➤${STR}Installing $MODULE..."
259
260
  mkdir -p logs
260
261
  export PIP_DISABLE_PIP_VERSION_CHECK=1
261
262
  INSTALL_ERRORS_FILE="logs/install_errors"
@@ -265,8 +266,8 @@
265
266
  fi
266
267
 
267
268
  if [[ -z $DEBUG ]]; then
268
- pip3 --disable-pip-version-check install -q $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
269
- red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
269
+ pip3 --default-timeout=300 --disable-pip-version-check install -q $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --default-timeout=300 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
270
+ red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
270
271
 
271
272
  if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
272
273
  cat "$INSTALL_ERRORS_FILE"
@@ -275,8 +276,8 @@
275
276
  exit 20
276
277
  }
277
278
  else
278
- pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
279
- red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
279
+ pip3 --default-timeout=300 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --default-timeout=300 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
280
+ red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
280
281
 
281
282
  if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
282
283
  cat "$INSTALL_ERRORS_FILE"
@@ -323,17 +324,25 @@
323
324
  MAX_NR="${#install_those[@]}"
324
325
  NUMBER_OF_INSTALLED_MODULES=$(get_nr_of_already_installed_modules)
325
326
 
326
- PROGRESSBAR=$(generate_progress_bar_setup "$MAX_NR")
327
+ MAX_PERCENT=100
327
328
 
328
329
  for key in "${!install_those[@]}"; do
330
+ idx=$((idx+1))
329
331
  install_this=${install_those[$key]}
330
- PROGRESSBAR=$(generate_progress_bar_setup "$MAX_NR")
332
+ percent=$((idx * 100 / MAX_NR))
333
+
334
+ PROGRESSBAR=$(generate_progress_bar "$idx" "$MAX_NR")
335
+
336
+ STR="Checking ${idx_padded}/${MAX_NR}, ${percent_padded}%: "
337
+
331
338
  if [[ -z $CI ]]; then
332
- green_reset_line "${PROGRESSBAR}➤Checking if $install_this is installed..."
339
+ printf -v idx_padded "%*d" "${#MAX_NR}" "$idx"
340
+ printf -v percent_padded "%*d" "${#MAX_PERCENT}" "$percent"
341
+ green_reset_line "${PROGRESSBAR}➤$STR$install_this..."
333
342
  fi
334
343
 
335
344
  if ! echo "$FROZEN" | grep -q "$install_this"; then
336
- ppip "$install_this" "-" "$MAX_NR"
345
+ ppip "$install_this" "-" "$MAX_NR" "$STR"
337
346
  fi
338
347
  done
339
348
 
@@ -451,7 +460,7 @@
451
460
  exit 20
452
461
  }
453
462
 
454
- downgrade_output=$(pip3 --disable-pip-version-check install -q pip==24.0) || {
463
+ downgrade_output=$(pip3 --default-timeout=300 --disable-pip-version-check install -q pip==24.0) || {
455
464
  red_text "Failed to downgrade pip. Output:"
456
465
  red_text "$downgrade_output"
457
466
  }
@@ -2,7 +2,8 @@ import sys
2
2
  import os
3
3
  import json
4
4
  import logging
5
- from typing import Optional
5
+ from typing import Optional, Any
6
+
6
7
  try:
7
8
  import optuna
8
9
  from optuna.trial import create_trial
@@ -52,7 +53,7 @@ def tpe_suggest_point(trial: optuna.Trial, parameters: dict) -> dict:
52
53
  if pvaltype == 'INT':
53
54
  point[param_name] = trial.suggest_int(param_name, rmin, rmax)
54
55
  elif pvaltype == 'FLOAT':
55
- point[param_name] = trial.suggest_float(param_name, rmin, rmax)
56
+ point[param_name] = trial.suggest_float(param_name, rmin, rmax) # type: ignore[assignment]
56
57
  else:
57
58
  raise ValueError(f"Unsupported type {pvaltype} for RANGE")
58
59
 
@@ -162,7 +163,7 @@ def add_existing_trial_to_study(study: optuna.study.study.Study, trial_entry: li
162
163
  )
163
164
 
164
165
  @beartype
165
- def get_best_or_new_point(study: optuna.study.study.Study, parameters: dict, direction: str) -> dict:
166
+ def get_best_or_new_point(study: Any, parameters: dict, direction: str) -> dict:
166
167
  best_trial_value = study.best_trial.value
167
168
  if best_trial_value is not None:
168
169
  if (direction == "minimize" and best_trial_value < 1e6) or \
@@ -5,7 +5,7 @@
5
5
  # Step 1:
6
6
  # It checks whether the environment already exists, and
7
7
  # if so, loads it.
8
- # If it doesn't exist. it creates it in
8
+ # If it doesn't exist, it creates it in
9
9
  # ~/.omniax_$(uname -m)_$(python3 --version | sed -e 's# #_#g')
10
10
  # i.e. e.g. ~/.omniax_x86_64_Python_3.11.2/ . This is done so that there
11
11
  # is no need for multiple installations, so that, once installed, it doesn't
@@ -31,7 +31,7 @@
31
31
  #SBATCH --signal=B:USR1@600
32
32
 
33
33
  {
34
- SCRIPT_DIR=$(dirname $(realpath "$0"))
34
+ SCRIPT_DIR=$(dirname "$(realpath "$0")")
35
35
 
36
36
  if [ -n "${SLURM_JOB_ID:-}" ] ; then
37
37
  set +e
@@ -52,7 +52,7 @@
52
52
  set -e
53
53
  fi
54
54
 
55
- source $SCRIPT_DIR/.colorfunctions.sh
55
+ source "$SCRIPT_DIR/.colorfunctions.sh"
56
56
 
57
57
  cancelled_manually=0
58
58
 
@@ -81,7 +81,7 @@
81
81
 
82
82
  function end_all_bg_processes {
83
83
  for bg_job_id in $(jobs -p | sed -e 's#.*][[:space:]]*+[[:space:]]*##' -e 's#[[:space:]].*##'); do
84
- kill $bg_job_id 2>/dev/null >/dev/null
84
+ kill "$bg_job_id" 2>/dev/null >/dev/null
85
85
  done
86
86
  }
87
87
 
@@ -110,8 +110,8 @@
110
110
 
111
111
  if (command -v sbatch >/dev/null && [[ -n "$SLURM_JOB_ID" ]]) || ! command -v sbatch >/dev/null; then
112
112
  already_logging_this_command=1
113
- exec 1> >(tee -ia $bash_logname)
114
- exec 2> >(tee -ia $bash_logname >& 2)
113
+ exec 1> >(tee -ia "$bash_logname")
114
+ exec 2> >(tee -ia "$bash_logname" >& 2)
115
115
  fi
116
116
  else
117
117
  echo "uuidgen is not installed. It's recommended you install it." >&2
@@ -124,7 +124,7 @@
124
124
  ram_children=0
125
125
 
126
126
  for pid in $(pgrep -P $$); do
127
- child_ram=$(grep VmRSS /proc/$pid/status 2>/dev/null | awk '{print $2 / 1024}')
127
+ child_ram=$(grep VmRSS "/proc/$pid/status" 2>/dev/null | awk '{print $2 / 1024}')
128
128
  ram_children=$(awk -v a="$ram_children" -v b="$child_ram" 'BEGIN {print a + b}')
129
129
  done
130
130
 
@@ -153,6 +153,7 @@
153
153
 
154
154
  if [[ -n $RUN_UUID ]]; then
155
155
  if ! [[ -e "logs/${RUN_UUID}_ram_log" ]]; then
156
+ mkdir -p logs
156
157
  echo "time,ram,ram_children" > "logs/${RUN_UUID}_ram_log"
157
158
  fi
158
159
 
@@ -169,7 +170,7 @@
169
170
  while true; do
170
171
  date_str=$(date +"%Y-%m-%d %H:%M:%S")
171
172
  echo -e "\n\n$date_str -> $(show_ram)\n\n" >&2
172
- sleep $n
173
+ sleep "$n"
173
174
  done
174
175
  }
175
176
 
@@ -210,7 +211,7 @@
210
211
  fi
211
212
 
212
213
  if [[ ! -e $file ]]; then
213
- echo "Cannot parse non-existant toml." >&2
214
+ echo "Cannot parse non-existent toml." >&2
214
215
  return 1
215
216
  fi
216
217
 
@@ -237,7 +238,7 @@
237
238
  fi
238
239
 
239
240
  if [[ ! -e "$file" ]]; then
240
- echo "Cannot parse non-existant yaml." >&2
241
+ echo "Cannot parse non-existent yaml." >&2
241
242
  return 1
242
243
  fi
243
244
 
@@ -269,7 +270,7 @@
269
270
  fi
270
271
 
271
272
  if [[ ! -e "$file" ]]; then
272
- echo "Cannot parse non-existant json." >&2
273
+ echo "Cannot parse non-existent json." >&2
273
274
  return 1
274
275
  fi
275
276
 
@@ -336,7 +337,7 @@
336
337
 
337
338
  int_re='^[+-]?[0-9]+$'
338
339
 
339
- if [[ -n $PRINT_SEPERATOR ]]; then # for tests, so that things are properly visually seperated
340
+ if [[ -n $PRINT_SEPARATOR ]]; then # for tests, so that things are properly visually separated
340
341
  echo ""
341
342
  echo "========================================================================"
342
343
  echo ""
@@ -345,10 +346,35 @@
345
346
  send_anonymized_usage_stats=0
346
347
  already_shown_oo_base_url_msg=0
347
348
 
349
+ function run_live_share {
350
+ if [[ $RUN_UUID != "" ]]; then
351
+ full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
352
+ if [[ -e "$full_log_file" ]]; then
353
+ set +e
354
+ run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
355
+ if [[ -z $run_folder ]]; then
356
+ true
357
+ else
358
+ bash "$SCRIPT_DIR/omniopt_share" --username="$USER" "$run_folder" 2>/dev/null >/dev/null
359
+ fi
360
+ set -e
361
+ else
362
+ red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
363
+ fi
364
+ fi
365
+ }
366
+
367
+ function start_periodic_live_share {
368
+ while true; do
369
+ run_live_share 2>/dev/null >/dev/null
370
+ sleep 10
371
+ done
372
+ }
373
+
348
374
  function myexit {
349
375
  CODE=$1
350
376
 
351
- end_all_bg_processes
377
+ end_all_bg_processes 2>/dev/null
352
378
 
353
379
  if [[ $follow -eq 1 ]]; then
354
380
  if [[ -z $CODE ]] || ! [[ $CODE =~ $int_re ]]; then
@@ -381,29 +407,15 @@
381
407
 
382
408
  if [[ $follow -eq 1 ]] || ! command -v sbatch 2>/dev/null >/dev/null || [[ $force_local_execution -eq 1 ]]; then
383
409
  if [[ $live_share -eq 1 ]]; then
384
- if [[ $RUN_UUID != "" ]]; then
385
- full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
386
- if [[ -e "$full_log_file" ]]; then
387
- set +e
388
- run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
389
- if [[ -z $run_folder ]]; then
390
- true
391
- else
392
- bash $SCRIPT_DIR/omniopt_share --username="$USER" "$run_folder" 2>/dev/null >/dev/null
393
- fi
394
- set -e
395
- else
396
- red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
397
- fi
398
- fi
410
+ run_live_share
399
411
  fi
400
412
  fi
401
413
 
402
- exit $CODE
414
+ exit "$CODE"
403
415
  }
404
416
 
405
417
  function get_anon_user_id {
406
- user_groups=$(echo "$(echo $USER | sha512sum)|groups=$(groups | tr ' ' '\n' | sort | sha512sum)")
418
+ user_groups=$(echo "$(echo "$USER" | sha512sum)|groups=$(groups | tr ' ' '\n' | sort | sha512sum)")
407
419
  fixed_iv=$(echo -n "$user_groups" | sha512sum | cut -c1-32)
408
420
  encrypted=$(echo -n "$user_groups" | openssl enc -aes-256-cbc -a -pass pass:"$(echo "$(groups | tr ' ' '\n' | sort | sha512sum)-$USER" | sha512sum | rev | sha512sum)" -iv "$fixed_iv" -nosalt -pbkdf2)
409
421
  echo "$encrypted" | sha512sum | rev | sha512sum | rev | sha512sum | sha512sum | sed -e 's#[[:space:]].*##' | cut -c1-32
@@ -499,7 +511,11 @@
499
511
  if [ $minutes -eq 1 ]; then
500
512
  result="in about $minutes minute"
501
513
  else
502
- result="in about $minutes minutes"
514
+ if [ $minutes -eq 0 ]; then
515
+ result="soon"
516
+ else
517
+ result="in about $minutes minutes"
518
+ fi
503
519
  fi
504
520
  echo "$result"
505
521
  return
@@ -600,7 +616,7 @@
600
616
 
601
617
  echo ""
602
618
  caller
603
- echo "Runtime (calltracer): $(displaytime $SECONDS), PID: $$"
619
+ echo "Runtime (calltracer): $(displaytime "$SECONDS"), PID: $$"
604
620
  else
605
621
  echo ""
606
622
  fi
@@ -619,7 +635,7 @@
619
635
  if [[ $python_pid =~ $re ]] ; then
620
636
  if [[ -z "$already_sent_signal" ]]; then
621
637
  if command -v ps 2>/dev/null >/dev/null; then
622
- if ps auxf | grep $python_pid 2>/dev/null >/dev/null; then
638
+ if ps auxf | grep "$python_pid" 2>/dev/null >/dev/null; then
623
639
  already_sent_signal=1
624
640
  echo -e "\nSending USR1 to $python_pid (python). Reason: $REASON"
625
641
  kill -USR1 "$python_pid"
@@ -632,7 +648,7 @@
632
648
  fi
633
649
 
634
650
  if [[ $kill_python_if_started_already_shown -eq 0 ]]; then
635
- echo "Runtime (kill_python_if_started): $(displaytime $SECONDS), PID: $$"
651
+ echo "Runtime (kill_python_if_started): $(displaytime "$SECONDS"), PID: $$"
636
652
  kill_python_if_started_already_shown=1
637
653
  fi
638
654
 
@@ -677,7 +693,7 @@
677
693
 
678
694
  printf "%02d:%02d:%02d\n" "$hours" "$minutes" "$seconds"
679
695
  elif [[ $var =~ $time_re ]]; then
680
- echo $var
696
+ echo "$var"
681
697
  else
682
698
  red_text "ERROR: $var is not a valid input. Must be a number of minutes (digits) or HH:MM:SS\n"
683
699
 
@@ -1004,6 +1020,10 @@ $complex_options_str
1004
1020
  args_string+=" --help "
1005
1021
  ;;
1006
1022
 
1023
+ --memray)
1024
+ export RUN_WITH_MEMRAY=1
1025
+ ;;
1026
+
1007
1027
  --flame_graph)
1008
1028
  export RUN_WITH_PYSPY=1
1009
1029
  ;;
@@ -1182,12 +1202,12 @@ EOF
1182
1202
  if [[ "$commits_since_tag" -gt 0 ]]; then
1183
1203
  if [[ "$checkout_to_latest_tested_version" -eq "1" ]]; then
1184
1204
  yellow_text "--checkout_to_latest_tested_version enabled. Checking out to $tag_commit_hash..."
1185
- git -C "$SCRIPT_DIR" checkout $tag_commit_hash >/dev/null 2>/dev/null || {
1205
+ git -C "$SCRIPT_DIR" checkout "$tag_commit_hash" >/dev/null 2>/dev/null || {
1186
1206
  red_text "\nFailed to checkout to latest version. Try not using --checkout_to_latest_tested_version.\n"
1187
1207
  myexit 211
1188
1208
  }
1189
1209
 
1190
- bash omniopt $*
1210
+ bash omniopt "$*"
1191
1211
  exit_code=$?
1192
1212
 
1193
1213
  myexit $exit_code
@@ -1619,14 +1639,29 @@ EOF
1619
1639
  set +e
1620
1640
  trap - ERR
1621
1641
 
1642
+ live_share_pid=""
1643
+
1644
+ if [[ $live_share -eq 1 ]]; then
1645
+ start_periodic_live_share &
1646
+ live_share_pid=$!
1647
+ fi
1648
+
1622
1649
  if [[ -z $RUN_WITH_COVERAGE ]]; then
1623
- if [[ -z $RUN_WITH_PYSPY ]]; then
1624
- stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
1625
- EXIT_CODE=$?
1626
- else
1650
+ if [[ -n $RUN_WITH_PYSPY ]]; then
1627
1651
  echo "Starting OmniOpt with Py-Spy"
1628
1652
  pip install py-spy
1629
- stdbuf -e 0 -o 0 py-spy record --rate 10 --subprocesses --native --output $RUN_UUID.svg python3 -- "$SCRIPT_DIR/.omniopt.py" $args_string
1653
+ stdbuf -e 0 -o 0 py-spy record --rate 10 --subprocesses --native --output "$RUN_UUID.svg" python3 -- "$SCRIPT_DIR/.omniopt.py" $args_string
1654
+ EXIT_CODE=$?
1655
+ elif [[ -n $RUN_WITH_MEMRAY ]]; then
1656
+ echo "Starting OmniOpt with MemRay."
1657
+ echo "Check later on with 'memray flamegraph $RUN_UUID.bin'"
1658
+ export PYTORCH_NO_CUDA_MEMORY_CACHING=1
1659
+ export PYTHONFAULTHANDLER=1
1660
+ pip install memray
1661
+ stdbuf -e 0 -o 0 memray run -o "$RUN_UUID.bin" -- "$SCRIPT_DIR/.omniopt.py" $args_string
1662
+ EXIT_CODE=$?
1663
+ else
1664
+ stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
1630
1665
  EXIT_CODE=$?
1631
1666
  fi
1632
1667
  else
@@ -1635,6 +1670,10 @@ EOF
1635
1670
  EXIT_CODE=$?
1636
1671
  fi
1637
1672
 
1673
+ if [[ $live_share -eq 1 ]] && [[ -n $live_share_pid ]]; then
1674
+ kill -9 $live_share_pid >/dev/null 2>/dev/null
1675
+ fi
1676
+
1638
1677
  set -e
1639
1678
  trap 'calltracer' ERR
1640
1679
 
@@ -1842,7 +1881,7 @@ EOF
1842
1881
  kill_tail_when_squeue_job_empty "$started_job_nr" &
1843
1882
 
1844
1883
  tail_log_file() {
1845
- trap 'ask_cancel' SIGINT
1884
+ #trap 'ask_cancel' SIGINT
1846
1885
  # weird exec stuff for disabling the "Terminated" message coming from kill
1847
1886
  exec 3>&2 # 3 is now a copy of 2
1848
1887
  exec 2> /dev/null # 2 now points to /dev/null
@@ -1881,39 +1920,37 @@ EOF
1881
1920
  tail_log_file
1882
1921
 
1883
1922
  if [[ $already_logging_this_command -eq 0 ]]; then
1884
- exec 1> >(tee -ia $bash_logname)
1885
- exec 2> >(tee -ia $bash_logname >& 2)
1923
+ exec 1> >(tee -ia "$bash_logname")
1924
+ exec 2> >(tee -ia "$bash_logname" >& 2)
1886
1925
  fi
1887
1926
 
1888
1927
 
1889
1928
  exit_code_lines=$(grep -i "exit-code:*" "$LOG_PATH" 2>/dev/null)
1890
- if [ $? -ne 0 ] || [ -z "$exit_code_lines" ]; then
1891
- echo "WARN: grep failed or no exit-code line found."
1929
+ exit_code_lines_lines=$?
1930
+ if [ $exit_code_lines_lines -ne 0 ] || [ -z "$exit_code_lines" ]; then
1892
1931
  exit_code_lines=""
1893
1932
  fi
1894
1933
 
1895
1934
  exit_code_sed=$(echo "$exit_code_lines" | sed -e 's#Exit-Code:*[[:space:]]*##i' -e 's#,.*##')
1896
- if [ $? -ne 0 ] || [ -z "$exit_code_sed" ]; then
1897
- echo "WARN: sed failed or no data after sed."
1935
+ exit_code_sed_sed=$?
1936
+ if [ $exit_code_sed_sed -ne 0 ] || [ -z "$exit_code_sed" ]; then
1898
1937
  exit_code_sed=""
1899
1938
  fi
1900
1939
 
1901
1940
  exit_code_tail=$(echo "$exit_code_sed" | tail -n1)
1902
- if [ $? -ne 0 ] || [ -z "$exit_code_tail" ]; then
1903
- echo "WARN: tail failed or no data after tail."
1941
+ exit_code_tail_tail=$?
1942
+ if [ $exit_code_tail_tail -ne 0 ] || [ -z "$exit_code_tail" ]; then
1904
1943
  exit_code_tail=""
1905
1944
  fi
1906
1945
 
1907
- exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+')
1946
+ exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+' | tail -n1)
1908
1947
  if [ -z "$exit_code_only_digits" ]; then
1909
- echo "WARN: No valid exit code found, setting it to 3"
1910
1948
  exit_code_only_digits=3
1911
1949
  fi
1912
1950
 
1913
1951
  exit_code="$exit_code_only_digits"
1914
1952
 
1915
1953
  if ! [[ "$exit_code" =~ ^[0-9]+$ ]]; then
1916
- echo "WARN: exit_code invalid ('$exit_code'), setting to 3"
1917
1954
  exit_code=3
1918
1955
  fi
1919
1956
 
@@ -1979,7 +2016,7 @@ EOF
1979
2016
  fi
1980
2017
 
1981
2018
  if [[ $show_runtime -eq 0 ]]; then
1982
- echo "Runtime (end): $(displaytime $SECONDS), PID: $$"
2019
+ echo "Runtime (end): $(displaytime "$SECONDS"), PID: $$"
1983
2020
  fi
1984
2021
 
1985
2022
  if [[ -n $RUN_WITH_COVERAGE ]]; then