amdgpu_fan 0.7.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/config/environment.rb +1 -0
- data/lib/amdgpu_fan/cli.rb +41 -30
- data/lib/amdgpu_fan/connector.rb +3 -3
- data/lib/amdgpu_fan/mixin/cli_output_format.rb +23 -7
- data/lib/amdgpu_fan/mixin/fan.rb +1 -1
- data/lib/amdgpu_fan/pci.rb +6 -2
- data/lib/amdgpu_fan/service.rb +3 -3
- data/lib/amdgpu_fan/stat_set.rb +1 -0
- data/lib/amdgpu_fan/version.rb +1 -1
- data/lib/amdgpu_fan/watcher.rb +18 -14
- metadata +48 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fb09354467c6ffeb603c4cbc72b131c626e83d4403148ebeb5fac342222ac29
|
4
|
+
data.tar.gz: b62420cbf660f704682f34565128c749216bb5605b3d57b843f4bc85671aa09c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9a94891e8024c9e2c58c46feb4b7654e69978a9215278d9588065db177e8df447670cad9be726f608f16bd77f4a26e2a05fe16c536ce42bce0c9242489d2b43
|
7
|
+
data.tar.gz: 8046858789272ed17ce75304f53ee3915973193bc81bd301335448456c99bd8d4d774962668b2b98388a24301e158d4cffb18a65a28d27c7fd45c130c639740d
|
data/config/environment.rb
CHANGED
data/lib/amdgpu_fan/cli.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/AbcSize, Metrics/ClassLength, Metrics/MethodLength
|
4
|
+
|
3
5
|
require 'yaml'
|
4
6
|
|
5
7
|
module AmdgpuFan
|
@@ -56,18 +58,19 @@ module AmdgpuFan
|
|
56
58
|
desc 'status [--logo]', 'View device info, current fan speed, and temperature.'
|
57
59
|
def status(option = nil)
|
58
60
|
puts radeon_logo if option == '--logo'
|
59
|
-
puts ICONS[:gpu] + ' GPU:'.ljust(9) + amdgpu_service.name
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
61
|
+
puts ICONS[:gpu] + ' GPU:'.ljust(9) + amdgpu_service.name
|
62
|
+
puts ICONS[:vbios] + ' vBIOS:'.ljust(9) + amdgpu_service.vbios_version
|
63
|
+
puts "#{ICONS[:display]} Displays:#{amdgpu_service.display_names.join(', ')}"
|
64
|
+
puts ICONS[:clock] + ' Clocks:'.ljust(9) + clock_status
|
65
|
+
puts ICONS[:memory] + ' Memory:'.ljust(9) + mem_total_mibibyes
|
66
|
+
puts ICONS[:fan] + ' Fan:'.ljust(9) + fan_status
|
67
|
+
puts ICONS[:temp] + ' Temp:'.ljust(9) + "#{amdgpu_service.temperature}°C"
|
68
|
+
puts ICONS[:power] + ' Power:'.ljust(9) +
|
69
|
+
"#{amdgpu_service.profile_mode} profile in " \
|
70
|
+
"#{amdgpu_service.power_dpm_state} mode using " \
|
71
|
+
"#{amdgpu_service.power_draw} / #{amdgpu_service.power_max} Watts "\
|
72
|
+
"(#{amdgpu_service.power_draw_percent}%)"
|
73
|
+
puts ICONS[:load] + ' Load:'.ljust(9) + percent_meter(amdgpu_service.busy_percent)
|
71
74
|
end
|
72
75
|
|
73
76
|
desc 'version', 'Print the application version.'
|
@@ -76,7 +79,7 @@ module AmdgpuFan
|
|
76
79
|
end
|
77
80
|
|
78
81
|
desc 'watch [SECONDS]', 'Watch fan speed, load, power, and temperature ' \
|
79
|
-
|
82
|
+
'refreshed every n seconds.'
|
80
83
|
def watch(seconds = 1)
|
81
84
|
return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
|
82
85
|
|
@@ -120,21 +123,21 @@ module AmdgpuFan
|
|
120
123
|
watcher.measure
|
121
124
|
5.times { print "\033[K\033[A" } # move up a line and clear to end of line
|
122
125
|
|
123
|
-
puts ICONS[:clock]
|
124
|
-
ICONS[:memory]
|
125
|
-
ICONS[:fan]
|
126
|
-
ICONS[:power]
|
127
|
-
ICONS[:temp]
|
126
|
+
puts "#{ICONS[:clock]} Core clock #{watcher.core_clock}",
|
127
|
+
"#{ICONS[:memory]} Memory clk #{watcher.memory_clock}",
|
128
|
+
"#{ICONS[:fan]} Fan speed #{watcher.fan_speed_rpm}",
|
129
|
+
"#{ICONS[:power]} Power usage #{watcher.power_draw}",
|
130
|
+
"#{ICONS[:temp]} Temperature #{watcher.temperature}"
|
128
131
|
sleep 1
|
129
132
|
end
|
130
133
|
end
|
131
134
|
|
132
135
|
desc 'watch_csv [SECONDS]', 'Watch stats in CSV format ' \
|
133
|
-
|
136
|
+
'refreshed every n seconds defaulting to 1 second.'
|
134
137
|
def watch_csv(seconds = 1)
|
135
138
|
return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
|
136
139
|
|
137
|
-
puts 'Timestamp,
|
140
|
+
puts 'Timestamp,Core Clock (Mhz),Memory Clock (Mhz),Fan speed (rpm),'\
|
138
141
|
'Load (%),Power (Watts),Temp (°C)'
|
139
142
|
|
140
143
|
trap 'SIGINT' do
|
@@ -142,13 +145,19 @@ module AmdgpuFan
|
|
142
145
|
end
|
143
146
|
|
144
147
|
loop do
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
148
|
+
list = []
|
149
|
+
threads = [
|
150
|
+
Thread.new { list[0] = amdgpu_service.core_clock },
|
151
|
+
Thread.new { list[1] = amdgpu_service.memory_clock },
|
152
|
+
Thread.new { list[2] = amdgpu_service.fan_speed_rpm },
|
153
|
+
Thread.new { list[3] = amdgpu_service.busy_percent },
|
154
|
+
Thread.new { list[4] = amdgpu_service.power_draw },
|
155
|
+
Thread.new { list[5] = amdgpu_service.temperature }
|
156
|
+
]
|
157
|
+
threads.each(&:join)
|
158
|
+
|
159
|
+
puts [Time.now.strftime('%F %T'), *list].join(',')
|
160
|
+
|
152
161
|
sleep seconds.to_i
|
153
162
|
end
|
154
163
|
end
|
@@ -165,7 +174,7 @@ module AmdgpuFan
|
|
165
174
|
|
166
175
|
def fan_status
|
167
176
|
"#{amdgpu_service.fan_mode} mode running at " \
|
168
|
-
|
177
|
+
"#{amdgpu_service.fan_speed_rpm} rpm (#{amdgpu_service.fan_speed_percent}%)"
|
169
178
|
end
|
170
179
|
|
171
180
|
def mem_total_mibibyes
|
@@ -177,8 +186,8 @@ module AmdgpuFan
|
|
177
186
|
end
|
178
187
|
|
179
188
|
def summary_clock
|
180
|
-
"Core: #{amdgpu_service.core_clock.rjust(7)}#{WATCH_FIELD_SEPARATOR}"\
|
181
|
-
"Memory: #{amdgpu_service.memory_clock.rjust(7)}"
|
189
|
+
"Core: #{amdgpu_service.core_clock.to_s.rjust(7)}#{WATCH_FIELD_SEPARATOR}"\
|
190
|
+
"Memory: #{amdgpu_service.memory_clock.to_s.rjust(7)}"
|
182
191
|
end
|
183
192
|
|
184
193
|
def summary_fan
|
@@ -201,3 +210,5 @@ module AmdgpuFan
|
|
201
210
|
end
|
202
211
|
end
|
203
212
|
end
|
213
|
+
|
214
|
+
# rubocop:enable Metrics/AbcSize, Metrics/ClassLength, Metrics/MethodLength
|
data/lib/amdgpu_fan/connector.rb
CHANGED
@@ -18,9 +18,9 @@ module AmdgpuFan
|
|
18
18
|
# Return an array of connector objects for the provided card number.
|
19
19
|
# The files are sorted to improve how they are displayed to the user.
|
20
20
|
def where(card_num:)
|
21
|
-
Dir["/sys/class/drm/card#{card_num}/card#{card_num}-*"].
|
22
|
-
Connector.new card_num
|
23
|
-
dir_path
|
21
|
+
Dir["/sys/class/drm/card#{card_num}/card#{card_num}-*"].map do |dir_path|
|
22
|
+
Connector.new card_num:,
|
23
|
+
dir_path:,
|
24
24
|
index: dir_path[-1],
|
25
25
|
type: dir_path.slice(/(?<=card#{card_num}-)[A-z]+/)
|
26
26
|
end
|
@@ -3,19 +3,35 @@
|
|
3
3
|
module AmdgpuFan
|
4
4
|
# A mixin to help with CLI output formatting
|
5
5
|
module CliOutputFormat
|
6
|
-
|
6
|
+
METER_CHARS = [' ', *("\u2588".."\u258F").to_a.reverse].freeze
|
7
7
|
TIME_FORMAT = '%F %T'
|
8
8
|
|
9
|
-
private
|
10
|
-
|
11
9
|
def current_time
|
12
10
|
Time.now.strftime(TIME_FORMAT)
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
##
|
14
|
+
# Return a string with meter and percentage for +percent+
|
15
|
+
#
|
16
|
+
def percent_meter(percent, width = 3)
|
17
|
+
meter_char_indexes = []
|
18
|
+
percent_portion_size = 100.0 / width
|
19
|
+
width.times do |i|
|
20
|
+
current_portion = percent.to_i - (percent_portion_size * i)
|
21
|
+
|
22
|
+
current_portion_percent = if current_portion >= percent_portion_size
|
23
|
+
1
|
24
|
+
elsif current_portion <= 0
|
25
|
+
0
|
26
|
+
else
|
27
|
+
current_portion / percent_portion_size
|
28
|
+
end
|
29
|
+
|
30
|
+
meter_char_indexes << ((METER_CHARS.length - 1) * current_portion_percent.to_f).round
|
31
|
+
end
|
32
|
+
|
33
|
+
percent_string = "#{format '%<num>0.2i', num: percent}%".ljust(4)
|
34
|
+
"#{percent_string}[#{meter_char_indexes.map { |i| METER_CHARS[i] }.join}]"
|
19
35
|
end
|
20
36
|
|
21
37
|
def radeon_logo
|
data/lib/amdgpu_fan/mixin/fan.rb
CHANGED
data/lib/amdgpu_fan/pci.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
4
|
+
|
3
5
|
require 'net/http'
|
4
6
|
|
5
7
|
module AmdgpuFan
|
@@ -44,8 +46,8 @@ module AmdgpuFan
|
|
44
46
|
hash[current_vendor_id][:devices][current_device_id] = { name: device_name }
|
45
47
|
elsif line[0..2] =~ /\t\t\w/
|
46
48
|
# Subvendor line
|
47
|
-
subvendor_id = line.split(' ').first.to_i(16)
|
48
|
-
subdevice_id = line.split
|
49
|
+
# subvendor_id = line.split(' ').first.to_i(16)
|
50
|
+
subdevice_id = line.split[1].to_i(16)
|
49
51
|
subdevice_name = line.split(' ')[1].strip
|
50
52
|
hash[current_vendor_id][:devices][current_device_id][subdevice_id] =
|
51
53
|
{ name: subdevice_name }
|
@@ -60,3 +62,5 @@ module AmdgpuFan
|
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
65
|
+
|
66
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
data/lib/amdgpu_fan/service.rb
CHANGED
@@ -31,7 +31,7 @@ module AmdgpuFan
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def connectors
|
34
|
-
@connectors ||= Connector.where card_num:
|
34
|
+
@connectors ||= Connector.where card_num:
|
35
35
|
end
|
36
36
|
|
37
37
|
def core_clock
|
@@ -78,7 +78,7 @@ module AmdgpuFan
|
|
78
78
|
# Return the fan speed in revolutions per minute
|
79
79
|
#
|
80
80
|
def fan_speed_rpm
|
81
|
-
File.read(fan_file(:input)).strip
|
81
|
+
File.read(fan_file(:input)).strip.to_i
|
82
82
|
end
|
83
83
|
|
84
84
|
##
|
@@ -159,7 +159,7 @@ module AmdgpuFan
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def clock_from_pp_file(file)
|
162
|
-
File.read(file).slice(/\w+(?= \*)/)
|
162
|
+
File.read(file).slice(/\w+(?= \*)/).to_i
|
163
163
|
end
|
164
164
|
|
165
165
|
def device_id
|
data/lib/amdgpu_fan/stat_set.rb
CHANGED
data/lib/amdgpu_fan/version.rb
CHANGED
data/lib/amdgpu_fan/watcher.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'async'
|
4
|
+
|
3
5
|
require_relative 'stat_set'
|
4
6
|
|
5
7
|
module AmdgpuFan
|
6
8
|
# Keep track of stats over time.
|
7
9
|
class Watcher
|
8
|
-
attr_reader :core_clock, :
|
10
|
+
attr_reader :core_clock, :fan_speed_rpm, :num_measurements, :memory_clock, :power_draw,
|
11
|
+
:temperature
|
9
12
|
|
10
13
|
def initialize(amdgpu_service)
|
11
14
|
@amdgpu_service = amdgpu_service
|
12
15
|
@num_measurements = 0
|
13
16
|
|
14
17
|
@core_clock = StatSet.new 'MHz'
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
18
|
+
@memory_clock = StatSet.new 'MHz'
|
19
|
+
@fan_speed_rpm = StatSet.new 'RPM'
|
20
|
+
@power_draw = StatSet.new 'W'
|
21
|
+
@temperature = StatSet.new '°C'
|
19
22
|
end
|
20
23
|
|
21
24
|
##
|
@@ -24,19 +27,20 @@ module AmdgpuFan
|
|
24
27
|
def measure
|
25
28
|
@num_measurements += 1
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
calculate_stats(stat_set)
|
30
|
+
Async do |task|
|
31
|
+
%i[core_clock fan_speed_rpm memory_clock power_draw temperature].each do |stat|
|
32
|
+
task.async do
|
33
|
+
send(stat).now = amdgpu_service.send(stat)
|
34
|
+
calculate_stats(send(stat))
|
35
|
+
end
|
36
|
+
end
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
private
|
39
41
|
|
42
|
+
attr_reader :amdgpu_service
|
43
|
+
|
40
44
|
def calculate_stats(stat_set)
|
41
45
|
if num_measurements == 1
|
42
46
|
stat_set.min = stat_set.now
|
@@ -47,7 +51,7 @@ module AmdgpuFan
|
|
47
51
|
|
48
52
|
stat_set.min = stat_set.now if stat_set.now < stat_set.min
|
49
53
|
stat_set.avg =
|
50
|
-
((stat_set.now + stat_set.avg * (num_measurements - 1)) / num_measurements.to_f)
|
54
|
+
((stat_set.now + (stat_set.avg * (num_measurements - 1))) / num_measurements.to_f)
|
51
55
|
.round(1)
|
52
56
|
stat_set.max = stat_set.now if stat_set.now > stat_set.max
|
53
57
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amdgpu_fan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin McCormack
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: async
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: thor
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,34 @@ dependencies:
|
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.1'
|
55
97
|
description: A CLI for interacting with the amdgpu Linux driver
|
56
98
|
email: harlemsquirrel@gmail.com
|
57
99
|
executables:
|
@@ -77,7 +119,8 @@ files:
|
|
77
119
|
homepage: https://github.com/HarlemSquirrel/amdgpu-fan-rb
|
78
120
|
licenses:
|
79
121
|
- MIT
|
80
|
-
metadata:
|
122
|
+
metadata:
|
123
|
+
rubygems_mfa_required: 'true'
|
81
124
|
post_install_message:
|
82
125
|
rdoc_options: []
|
83
126
|
require_paths:
|
@@ -86,14 +129,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
129
|
requirements:
|
87
130
|
- - ">="
|
88
131
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
132
|
+
version: 3.1.0
|
90
133
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
134
|
requirements:
|
92
135
|
- - ">="
|
93
136
|
- !ruby/object:Gem::Version
|
94
137
|
version: '0'
|
95
138
|
requirements: []
|
96
|
-
rubygems_version: 3.
|
139
|
+
rubygems_version: 3.3.3
|
97
140
|
signing_key:
|
98
141
|
specification_version: 4
|
99
142
|
summary: A CLI to view and set fan speeds for AMD graphics cards running on the open
|