powerlog 0.0.1__tar.gz

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.
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="Python 3.12 (powerlog)" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (powerlog)" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/powerlog.iml" filepath="$PROJECT_DIR$/.idea/powerlog.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/.venv" />
6
+ </content>
7
+ <orderEntry type="jdk" jdkName="Python 3.12 (powerlog)" jdkType="Python SDK" />
8
+ <orderEntry type="sourceFolder" forTests="false" />
9
+ </component>
10
+ </module>
@@ -0,0 +1,81 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AutoImportSettings">
4
+ <option name="autoReloadType" value="SELECTIVE" />
5
+ </component>
6
+ <component name="ChangeListManager">
7
+ <list default="true" id="4ef7608a-8f08-4a0e-91d4-612ae53ad9fc" name="Changes" comment="" />
8
+ <option name="SHOW_DIALOG" value="false" />
9
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
10
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
11
+ <option name="LAST_RESOLUTION" value="IGNORE" />
12
+ </component>
13
+ <component name="ProjectColorInfo"><![CDATA[{
14
+ "associatedIndex": 3
15
+ }]]></component>
16
+ <component name="ProjectId" id="2zIXWyB0VVxNT3eQh5fkkI5Lg6L" />
17
+ <component name="ProjectViewState">
18
+ <option name="hideEmptyMiddlePackages" value="true" />
19
+ <option name="showLibraryContents" value="true" />
20
+ </component>
21
+ <component name="PropertiesComponent"><![CDATA[{
22
+ "keyToString": {
23
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
24
+ "RunOnceActivity.ShowReadmeOnStart": "true",
25
+ "last_opened_file_path": "/media/shovon/Codes/GithubCodes/powerlog",
26
+ "node.js.detected.package.eslint": "true",
27
+ "node.js.detected.package.tslint": "true",
28
+ "node.js.selected.package.eslint": "(autodetect)",
29
+ "node.js.selected.package.tslint": "(autodetect)",
30
+ "nodejs_package_manager_path": "npm",
31
+ "vue.rearranger.settings.migration": "true"
32
+ }
33
+ }]]></component>
34
+ <component name="RunManager">
35
+ <configuration name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
36
+ <module name="powerlog" />
37
+ <option name="ENV_FILES" value="" />
38
+ <option name="INTERPRETER_OPTIONS" value="" />
39
+ <option name="PARENT_ENVS" value="true" />
40
+ <envs>
41
+ <env name="PYTHONUNBUFFERED" value="1" />
42
+ </envs>
43
+ <option name="SDK_HOME" value="" />
44
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
45
+ <option name="IS_MODULE_SDK" value="true" />
46
+ <option name="ADD_CONTENT_ROOTS" value="true" />
47
+ <option name="ADD_SOURCE_ROOTS" value="true" />
48
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
49
+ <option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
50
+ <option name="PARAMETERS" value="" />
51
+ <option name="SHOW_COMMAND_LINE" value="false" />
52
+ <option name="EMULATE_TERMINAL" value="false" />
53
+ <option name="MODULE_MODE" value="false" />
54
+ <option name="REDIRECT_INPUT" value="false" />
55
+ <option name="INPUT_FILE" value="" />
56
+ <method v="2" />
57
+ </configuration>
58
+ </component>
59
+ <component name="SharedIndexes">
60
+ <attachedChunks>
61
+ <set>
62
+ <option value="bundled-js-predefined-d6986cc7102b-b26f3e71634d-JavaScript-PY-251.26094.141" />
63
+ <option value="bundled-python-sdk-9f8e2b94138c-36ea0e71a18c-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-251.26094.141" />
64
+ </set>
65
+ </attachedChunks>
66
+ </component>
67
+ <component name="TaskManager">
68
+ <task active="true" id="Default" summary="Default task">
69
+ <changelist id="4ef7608a-8f08-4a0e-91d4-612ae53ad9fc" name="Changes" comment="" />
70
+ <created>1751419597209</created>
71
+ <option name="number" value="Default" />
72
+ <option name="presentableId" value="Default" />
73
+ <updated>1751419597209</updated>
74
+ <workItem from="1751419598405" duration="1599000" />
75
+ </task>
76
+ <servers />
77
+ </component>
78
+ <component name="TypeScriptGeneratedFilesManager">
79
+ <option name="version" value="3" />
80
+ </component>
81
+ </project>
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ## 0.0.1 (2025-07-01)
4
+ - Initial release
powerlog-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ahmedur Rahman Shovon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: powerlog
3
+ Version: 0.0.1
4
+ Summary: GPU power log
5
+ Project-URL: Homepage, https://github.com/arsho/powerlog
6
+ Project-URL: Issues, https://github.com/arsho/powerlog/issues
7
+ Author-email: Ahmedur Rahman Shovon <shovon.sylhet@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: energy,gpupower,power analysis,power log,powerlog
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+
17
+ # powerlog
18
+
19
+ **Powerlog** is a lightweight command-line tool and Python package to profile GPU power consumption during the execution of a command-line program. It uses `nvidia-smi` to sample power draw at regular intervals and reports total energy usage, average power, and min/max readings.
20
+
21
+ ## Features
22
+
23
+ * Measures real-time GPU power draw using `nvidia-smi`
24
+ * Computes:
25
+
26
+ * Total runtime
27
+ * Total energy consumed (in Joules)
28
+ * Average, min, and max power (Watts)
29
+ * Outputs both summary and raw samples as CSV
30
+ * Simple CLI interface
31
+
32
+ ## Installation
33
+
34
+ Requires Python 3.6+ and NVIDIA's `nvidia-smi` available in your system PATH.
35
+
36
+ ```bash
37
+ pip install powerlog
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ```bash
43
+ powerlog --output power_report.csv --gpu 2 ./my_gpu_program arg1 arg2
44
+ ```
45
+
46
+ ### CLI Options
47
+
48
+ | Argument | Description |
49
+ | ------------ | ------------------------------------------- |
50
+ | `--output` | Base name for the output CSV files |
51
+ | `--gpu` | Number of GPUs to monitor (default: 1) |
52
+ | `cmd` | Command and arguments to run and profile |
53
+
54
+ ## Output
55
+
56
+ If `--output power.csv` is specified:
57
+
58
+ * `power.csv`: Summary of runtime, energy, and power stats
59
+ * `power_samples.csv`: Raw timestamped power draw samples
60
+
61
+ ## Example
62
+
63
+ ```bash
64
+ powerlog --output matrix_power.csv --gpu 1 ./matrix_multiply data/input.bin
65
+ powerlog --output matrix_power.csv --gpu 1 nvidia-smi
66
+ ```
67
+
68
+ ## Dependencies
69
+
70
+ * Python standard library (`subprocess`, `argparse`, `time`, `csv`)
71
+ * NVIDIA GPU with drivers and `nvidia-smi` tool
72
+
73
+ ## License
74
+
75
+ MIT License
76
+
77
+ ## Acknowledgments
78
+
79
+ Developed as part of GPU power-efficiency profiling experiments in Datalog-based engines.
@@ -0,0 +1,63 @@
1
+ # powerlog
2
+
3
+ **Powerlog** is a lightweight command-line tool and Python package to profile GPU power consumption during the execution of a command-line program. It uses `nvidia-smi` to sample power draw at regular intervals and reports total energy usage, average power, and min/max readings.
4
+
5
+ ## Features
6
+
7
+ * Measures real-time GPU power draw using `nvidia-smi`
8
+ * Computes:
9
+
10
+ * Total runtime
11
+ * Total energy consumed (in Joules)
12
+ * Average, min, and max power (Watts)
13
+ * Outputs both summary and raw samples as CSV
14
+ * Simple CLI interface
15
+
16
+ ## Installation
17
+
18
+ Requires Python 3.6+ and NVIDIA's `nvidia-smi` available in your system PATH.
19
+
20
+ ```bash
21
+ pip install powerlog
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```bash
27
+ powerlog --output power_report.csv --gpu 2 ./my_gpu_program arg1 arg2
28
+ ```
29
+
30
+ ### CLI Options
31
+
32
+ | Argument | Description |
33
+ | ------------ | ------------------------------------------- |
34
+ | `--output` | Base name for the output CSV files |
35
+ | `--gpu` | Number of GPUs to monitor (default: 1) |
36
+ | `cmd` | Command and arguments to run and profile |
37
+
38
+ ## Output
39
+
40
+ If `--output power.csv` is specified:
41
+
42
+ * `power.csv`: Summary of runtime, energy, and power stats
43
+ * `power_samples.csv`: Raw timestamped power draw samples
44
+
45
+ ## Example
46
+
47
+ ```bash
48
+ powerlog --output matrix_power.csv --gpu 1 ./matrix_multiply data/input.bin
49
+ powerlog --output matrix_power.csv --gpu 1 nvidia-smi
50
+ ```
51
+
52
+ ## Dependencies
53
+
54
+ * Python standard library (`subprocess`, `argparse`, `time`, `csv`)
55
+ * NVIDIA GPU with drivers and `nvidia-smi` tool
56
+
57
+ ## License
58
+
59
+ MIT License
60
+
61
+ ## Acknowledgments
62
+
63
+ Developed as part of GPU power-efficiency profiling experiments in Datalog-based engines.
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "powerlog"
7
+ version = "0.0.1"
8
+ dependencies = []
9
+ requires-python = ">=3.8"
10
+ authors = [
11
+ {name = "Ahmedur Rahman Shovon", email = "shovon.sylhet@gmail.com"},
12
+ ]
13
+ description = "GPU power log"
14
+ readme = "README.md"
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ "Development Status :: 4 - Beta"
19
+ ]
20
+ license = "MIT"
21
+ license-files = ["LICEN[CS]E*"]
22
+ keywords = ["powerlog", "gpupower", "energy", "power analysis", "power log"]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/arsho/powerlog"
26
+ Issues = "https://github.com/arsho/powerlog/issues"
@@ -0,0 +1,128 @@
1
+ import subprocess
2
+ import sys
3
+ import time
4
+ import csv
5
+ import argparse
6
+
7
+ NS_IN_S = 1_000_000_000 # Nanoseconds in a second
8
+
9
+ def log(message):
10
+ print(message, file=sys.stdout)
11
+
12
+ def get_power_draw(total_gpu_on_node=1):
13
+ proc = subprocess.run(
14
+ ["nvidia-smi", "--query-gpu=power.draw", "--format=csv,noheader,nounits"],
15
+ capture_output=True
16
+ )
17
+ stdout = proc.stdout.decode("utf-8").strip()
18
+ power_values = [float(line.strip()) for line in stdout.splitlines()]
19
+ return sum(power_values[:total_gpu_on_node])
20
+
21
+ def measure_power(cmd_args, resolution=0.1, total_gpu_on_node=1):
22
+ get_power_draw() # warm-up
23
+ energy_j = 0
24
+ power_draw_samples = []
25
+
26
+ proc = subprocess.Popen(cmd_args)
27
+ start_time_ns = time.time_ns()
28
+ time_ns = start_time_ns
29
+
30
+ while True:
31
+ try:
32
+ proc.wait(timeout=resolution)
33
+ except subprocess.TimeoutExpired:
34
+ new_time_ns = time.time_ns()
35
+ draw_w = get_power_draw()
36
+ delay_ns = new_time_ns - time_ns
37
+ energy_j += delay_ns * draw_w / NS_IN_S
38
+ power_draw_samples.append((new_time_ns, draw_w))
39
+ time_ns = new_time_ns
40
+ else:
41
+ break
42
+
43
+ end_time_ns = time_ns
44
+ total_time_s = (end_time_ns - start_time_ns) / NS_IN_S
45
+ sampled_draws = [v[1] for v in power_draw_samples]
46
+ avg_power_sampled = sum(sampled_draws) / len(sampled_draws)
47
+ avg_power_timed = energy_j / total_time_s
48
+ min_draw = min(sampled_draws)
49
+ max_draw = max(sampled_draws)
50
+
51
+ return {
52
+ "total_time_s": total_time_s,
53
+ "energy_j": energy_j,
54
+ "avg_power_sampled": avg_power_sampled,
55
+ "avg_power_timed": avg_power_timed,
56
+ "min_draw": min_draw,
57
+ "max_draw": max_draw,
58
+ "samples": power_draw_samples
59
+ }
60
+
61
+ def save_summary_csv(path, result):
62
+ with open(path, 'w', newline='') as csvfile:
63
+ writer = csv.writer(csvfile)
64
+ writer.writerow([
65
+ "Total Time (s)",
66
+ "Total Energy (J)",
67
+ "Avg Power Sampled (W)",
68
+ "Avg Power Timed (W)",
69
+ "Min Power Sampled (W)",
70
+ "Max Power Sampled (W)"
71
+ ])
72
+ writer.writerow([
73
+ f"{result['total_time_s']:.4f}",
74
+ f"{result['energy_j']:.4f}",
75
+ f"{result['avg_power_sampled']:.4f}",
76
+ f"{result['avg_power_timed']:.4f}",
77
+ f"{result['min_draw']:.2f}",
78
+ f"{result['max_draw']:.2f}"
79
+ ])
80
+
81
+ def save_samples_csv(path, samples):
82
+ with open(path, 'w', newline='') as csvfile:
83
+ writer = csv.writer(csvfile)
84
+ writer.writerow(["Timestamp (ns)", "Power Draw (W)"])
85
+ for t_ns, draw in samples:
86
+ writer.writerow([t_ns, f"{draw:.2f}"])
87
+
88
+ def main():
89
+ parser = argparse.ArgumentParser(description="Measure GPU power during execution.")
90
+ parser.add_argument("cmd", nargs=argparse.REMAINDER, help="Command to run (mandatory)")
91
+ parser.add_argument("--output", type=str, help="Output CSV base name (optional)")
92
+ parser.add_argument("--gpu", type=int, default=1, help="Number of GPUs per node (default 1)")
93
+
94
+ try:
95
+ args = parser.parse_args()
96
+ except:
97
+ parser.print_help()
98
+ sys.exit(0)
99
+
100
+ log(f"Running command: {' '.join(args.cmd)} on {args.gpu} GPU")
101
+ result = measure_power(args.cmd, total_gpu_on_node = args.gpu)
102
+
103
+ # Display to stdout
104
+ log("\n" + "=" * 60)
105
+ log("GPU POWER USAGE SUMMARY")
106
+ log(f"Total Time: {result['total_time_s']:.4f} s")
107
+ log(f"Total Energy: {result['energy_j']:.4f} J")
108
+ log(f"Avg Power (Timed): {result['avg_power_timed']:.4f} W")
109
+ log(f"Avg Power (Sampled): {result['avg_power_sampled']:.4f} W")
110
+ log(f"Min Power (Sampled): {result['min_draw']:.2f} W")
111
+ log(f"Max Power (Sampled): {result['max_draw']:.2f} W")
112
+ log("=" * 60)
113
+
114
+ # Save to CSVs if output requested
115
+ if args.output:
116
+ summary_csv = args.output if args.output.endswith(".csv") else args.output + ".csv"
117
+ samples_csv = summary_csv.replace(".csv", "_samples.csv")
118
+ save_summary_csv(summary_csv, result)
119
+ save_samples_csv(samples_csv, result["samples"])
120
+ log(f"Saved summary to: {summary_csv}")
121
+ log(f"Saved power samples to: {samples_csv}")
122
+
123
+ if __name__ == "__main__":
124
+ main()
125
+
126
+
127
+ # python power_time.py --output power_report.csv --gpu 4 ./tc.out data/data_7035.bin 0 0 1
128
+ # python power_time.py --output power_report.csv --gpu 4 ./tc.out data/data_7035.bin 0 0 1