diff --git a/hpvm/docs/components/hpvm-profiler.rst b/hpvm/docs/components/hpvm-profiler.rst
index 8a0e6603d3b7111d2735a86b5db26d7aa834ebb6..820456799ddf0570be6b92564e35077e31fcd3da 100644
--- a/hpvm/docs/components/hpvm-profiler.rst
+++ b/hpvm/docs/components/hpvm-profiler.rst
@@ -1,6 +1,6 @@
 HPVM Profiler API
 ======================
 
-.. autofunction:: hpvm_profiler.profile_configs
+.. autofunction:: hpvm_profiler.profile_config_file
 
 .. autofunction:: hpvm_profiler.plot_hpvm_configs
diff --git a/hpvm/docs/getting-started.rst b/hpvm/docs/getting-started.rst
index cbf5d0b095c1035acf8bfcc7aaccf1d3cb0be3ce..7b6b3074275c7e693270fe658223e5183b76816d 100644
--- a/hpvm/docs/getting-started.rst
+++ b/hpvm/docs/getting-started.rst
@@ -207,14 +207,14 @@ we obtained in the tuning step.
 
 .. code-block:: python
 
-   from hpvm_profiler import profile_configs, plot_hpvm_configs
+   from hpvm_profiler import profile_config_file, plot_hpvm_configs
 
    # Set `target_binary` to the path of the plain binary.
    target_binary = "./alexnet2_cifar10/build/alexnet2_cifar10"
    # Set `config_file` to the config file produced in tuning, such as "hpvm_confs.txt".
    config_file = "hpvm_confs.txt"
    out_config_file = "hpvm_confs_profiled.txt"
-   profile_configs(target_binary, config_file, out_config_file)
+   profile_config_file(target_binary, config_file, out_config_file)
    plot_hpvm_configs(out_config_file, "configs_profiled.png")
 
 ``hpvm_confs_profiled.txt`` contains the profiled configurations in HPVM format,
diff --git a/hpvm/projects/hpvm-profiler/hpvm_profiler/__init__.py b/hpvm/projects/hpvm-profiler/hpvm_profiler/__init__.py
index 4e91fbbe4a4af2c16b7583443360a09d88b0ac61..594a96b202e0526e3c3dae5263b195fc8db95a94 100644
--- a/hpvm/projects/hpvm-profiler/hpvm_profiler/__init__.py
+++ b/hpvm/projects/hpvm-profiler/hpvm_profiler/__init__.py
@@ -4,16 +4,16 @@ from subprocess import PIPE, CalledProcessError
 from typing import Iterable, List, Tuple, Union
 
 import matplotlib.pyplot as plt
-from tqdm import trange
 
 PathLike = Union[Path, str]
 conf_opening, conf_closing = "+++++", "-----"
 
 
-def profile_configs(
+def profile_config_file(
     binary_path: PathLike,
     config_path: PathLike,
     output_config_path: PathLike,
+    progress_bar: bool = True,
     profile_filename: str = "profile_info.txt",
     qos_filename: str = "final_accuracy",
 ) -> None:
@@ -33,39 +33,64 @@ def profile_configs(
         It contains a single float number as the QoS of this run.
         This defaults to "final_accuracy" and should not be changed for HPVM binaries.
     """
-
-    from subprocess import check_call
-    from tempfile import NamedTemporaryFile
-
     # Read first line ("the float") and configs in config file
     header, configs = read_hpvm_configs(Path(config_path))
     if not configs:
         raise ValueError("Config file with no configs is unsupported.")
-    temp_file = NamedTemporaryFile("w")
-    baseline_time, baseline_acc = None, None
-    for idx in trange(len(configs), desc="Configs profiled"):
-        config = configs[idx]
-        # Write config to temp config file
-        write_hpvm_config(header, [config], Path(temp_file.name))
-        # Run binary_path binary,
-        # which generates `profile_filename` and `qos_filename` file in cwd.
-        try:
-            check_call([str(binary_path), "-c", str(temp_file.name)])     
-        except CalledProcessError as e:
-            print("Output from the program:")
-            print(e.output)
-            raise e
-        # Read these two files for time and QoS info.
-        time = _read_profile_file(Path(profile_filename))
-        acc = _read_qos_file(Path(qos_filename))
-        if idx == 0:
-            baseline_time, baseline_acc = time, acc
-            continue
-        assert baseline_time is not None and baseline_acc is not None
+    # Modifies configs in place.
+    profile_configs(
+        binary_path, configs[1:], configs[0], progress_bar, profile_filename, qos_filename
+    )
+    write_hpvm_configs(header, configs, Path(output_config_path))
+
+
+def profile_configs(
+    binary_path: PathLike,
+    configs: Iterable["Config"],
+    baseline_config: "Config",
+    progress_bar: bool = True,
+    profile_filename: str = "profile_info.txt",
+    qos_filename: str = "final_accuracy",
+) -> None:
+    """Profile a sequence of HPVM configs.
+    This function modifies argument `configs` in place."""
+
+    from tqdm import tqdm
+
+    baseline_time, baseline_acc = profile_config(binary_path, baseline_config)
+    iterable = tqdm(configs, desc="Configs profiled") if progress_bar else configs
+    for idx in iterable:
+        time, acc = profile_config(binary_path, config, profile_filename, qos_filename)
         speedup = baseline_time / time
         config.update_profile_results(speedup, acc, baseline_acc)
-    write_hpvm_config(header, configs, Path(output_config_path))
+    return configs
+
+
+def measure_config(
+    binary_path: PathLike,
+    config: "Config",
+    profile_filename: str = "profile_info.txt",
+    qos_filename: str = "final_accuracy",
+):
+    from subprocess import check_call
+    from tempfile import NamedTemporaryFile
+    import os
+
+    temp_file = NamedTemporaryFile("w")
+    write_hpvm_configs("0.0", [config], Path(temp_file.name))
+    # Run binary_path binary,
+    # which generates `profile_filename` and `qos_filename` file in cwd.
+    try:
+        with open(os.devnull, "w") as f:
+            check_call([str(binary_path), "-c", str(temp_file.name)], stdout=f)
+    except CalledProcessError as e:
+        print("Output from the program:")
+        print(e.output)
+        raise e
+    time = _read_profile_file(Path(profile_filename))
+    acc = _read_qos_file(Path(qos_filename))
     temp_file.close()
+    return time, acc
 
 
 def plot_hpvm_configs(
@@ -157,8 +182,7 @@ def read_hpvm_configs(config_file: PathLike) -> Tuple[str, List[Config]]:
     return header, ret_configs
 
 
-def write_hpvm_config(header: str, configs: Iterable[Config], to_file: PathLike):
-    
+def write_hpvm_configs(header: str, configs: Iterable[Config], to_file: PathLike):
     text_segs = [header] + [str(config) for config in configs]
     with open(to_file, "w") as f:
         f.write("\n".join(text_segs))