Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Nvidia GPU Fan Tweaker Script
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
szpko
n00b
n00b


Joined: 24 Apr 2014
Posts: 9

PostPosted: Thu Apr 24, 2014 2:29 pm    Post subject: Nvidia GPU Fan Tweaker Script Reply with quote

...

Last edited by szpko on Fri Aug 01, 2014 2:12 pm; edited 10 times in total
Back to top
View user's profile Send private message
steveL
Advocate
Advocate


Joined: 13 Sep 2006
Posts: 3042
Location: The Peanut Gallery

PostPosted: Thu Apr 24, 2014 7:29 pm    Post subject: Reply with quote

Ugh ancient and absolutely typical of most distros: we call that kind of script "bashish", since it has a /bin/bash shebang, but is written for sh, only it relies on some bashisms, and doesn't even know clean sh. The use of eval is totally unnecessary. Personally I'd rewrite it for pure sh:
Code:
#!/bin/sh
current_speed=$(nvidia-settings -t -q '[fan:0]/GPUCurrentFanSpeed') || exit
 
case $1 in
   up) new_speed=$((current_speed + 10))
      [ 100 -lt "$new_speed" ] && new_speed=100
;; down) new_speed=$((current_speed - 10))
      [ 35 -gt "$new_speed" ] && new_speed=35
;; *) exit 1
esac
exec nvidia-settings -a '[gpu:0]/GPUFanControlState=1' -a "[fan:0]/GPUCurrentFanSpeed=$new_speed"

I'm not sure it's such a good idea for the user to manually set the fan speed, mind; the batch scan looked more useful. But you could use the above with /bin/sh symlinked to any shell conformant to POSIX, /bin/bb or dash for example, as well as bash.

If you're not going to exit from the first command if it fails, then move the checks of range below the case statement; but I would, even if you decide to use: || exit 0 (though exit status is typically useful to other components.) The exit status of the last command run (or in this case we exec for efficiency) will be the exit status of the script. If you don't want that, remove the exec and add exit 0 to end (though again, I'd question the validity of that.)
Back to top
View user's profile Send private message
szpko
n00b
n00b


Joined: 24 Apr 2014
Posts: 9

PostPosted: Fri Apr 25, 2014 1:49 am    Post subject: Reply with quote

...

Last edited by szpko on Fri Aug 01, 2014 2:13 pm; edited 1 time in total
Back to top
View user's profile Send private message
steveL
Advocate
Advocate


Joined: 13 Sep 2006
Posts: 3042
Location: The Peanut Gallery

PostPosted: Sat Apr 26, 2014 7:58 pm    Post subject: Reply with quote

You're welcome, szpko; only it's not a "Bash script" any more, is it? ;) I'd edit the title/subject of OP and s/Bash/nvidia, as well as first line.

BTW, you shouldn't use unquoted globbing chars in script (unless you are trying to glob), however unlikely a match is; '[abc]' is a one-of char match in shell, when unquoted, and a string when it has '..' (or ".." but if it's literal, single-quoting is better afaic.) '*' and '?' are the other two to watch out for (as well ofc as spaces, and most punctuation, but not '.' or '/'.)

Didn't mean that there's no valid reason to tweak the fan speed; just that I'd be more interested in it being automatic. I didn't know nvidia default to 10% speed; I assumed it just varies with temperature. I have always got on with nvidia on Linux, so I'm curious now.

Thanks for putting in the legwork to find out more about it all, and taking the time to document.
Back to top
View user's profile Send private message
szpko
n00b
n00b


Joined: 24 Apr 2014
Posts: 9

PostPosted: Sun Apr 27, 2014 1:51 am    Post subject: Reply with quote

...

Last edited by szpko on Fri Aug 01, 2014 2:13 pm; edited 1 time in total
Back to top
View user's profile Send private message
Chiitoo
l33t
l33t


Joined: 28 Feb 2010
Posts: 922
Location: Here and Away Again

PostPosted: Sun Apr 27, 2014 2:17 am    Post subject: ><)))°€ Reply with quote

Some cool bits indeed you've got there. ^^

Thanks for sharing!

steveL wrote:
Didn't mean that there's no valid reason to tweak the fan speed; just that I'd be more interested in it being automatic. I didn't know nvidia default to 10% speed; I assumed it just varies with temperature. I have always got on with nvidia on Linux, so I'm curious now.

For what it's worth, mine seems to default to 40, and I can't set it lower than 30, at least not via the nvidia-settings GUI.

I don't seem to have any sort of automagic happening (at least not within the temps I try to keep it, that's around 60°C at most... due to the noise levels it puts out, though I think it has gone beyond 70°C when I forget to adjust the speed; perhaps it would start fanning up beyond that, but I've not tested). So, I have to fiddle with coolbits to gain access (even though the fan tool-tip says one should never have to enable it).

Normally I set it down to 30, or let it be at 40-50 when I have things going that make heat happen. Sometimes even 60! At 100 it gets just silly.

This is with an Asus (EN)GTX 275.
_________________
Kind Regards,
~ The Noob Unlimited ~

Sore wa sore, kore wa kore.
Back to top
View user's profile Send private message
steveL
Advocate
Advocate


Joined: 13 Sep 2006
Posts: 3042
Location: The Peanut Gallery

PostPosted: Mon Apr 28, 2014 2:51 pm    Post subject: Reply with quote

Heh I didn't even know about coolbits, and really must explore that GUI a bit more.. ;)
Back to top
View user's profile Send private message
krinn
Advocate
Advocate


Joined: 02 May 2003
Posts: 4433

PostPosted: Mon Nov 10, 2014 11:40 am    Post subject: Reply with quote

szepko you should put some comments stating your stuff doesn't work or isn't update or anything, but cleaning everything for no reason you should be kick in the balls.

Here's a python script doing that for poor guys coming here :
Code:
#!/usr/bin/env python
"""
Script to control the fan speed of an NVidia gpu using a custom fan speed/temperature curve.
Copyright (C) 2012  Luke Frisken

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses.
"""

from subprocess import *
import time
import os
import sys
import signal
import threading

"""
SETUP:
In order to get this program to work, my xorg.conf was generated
and saved using the x server display configuration tab in nvidia-settings.
These lines:

   Section "Device"
      Identifier     "Device0"
      Driver         "nvidia"
      VendorName     "NVIDIA Corporation"
      BoardName      "GeForce GTX 570"
   EndSection

in /etc/X11/xorg.conf
were then edited to look like this:

   Section "Device"
      Identifier     "Device0"
      Driver         "nvidia"
      VendorName     "NVIDIA Corporation"
      BoardName      "GeForce GTX 570"
      Option "Coolbits" "4"
   EndSection

then the compter is restarted.


RUNNING:
There are a few bugs which I haven't been able to solve, so observe carefully here:
 - try to run from an already open terminal.
 - try to end program using ctrl-C
 - ensure that when finished, the box in nvidia-settings for the manual fan control is unticked!!!!!
"""
class Vector():
   def __init__(self, x, y):
      self.x = x
      self.y = y

   def gradient(self):
      return float(y)/float(x)

   def __str__(self):
      return "Vector: {0}, {1}".format(self.x, self.y)


class Curve():
   def __init__(self, curve_point_array):
      #convert curve to use vectors for points
      """self.vector_curve = []
      for v in curve:
         self.vector_curve.append(Vector(v[0], v[1]))"""

      self.cpa = curve_point_array

   def evaluate(self, x):
      point_i = 0
      while(point_i < len(self.cpa) - 1):

         if(self.cpa[point_i][0] <= x and self.cpa[point_i + 1][0] > x):
            point_1 = self.cpa[point_i]
            point_2 = self.cpa[point_i + 1]
            delta_x = point_2[0] - point_1[0]
            delta_y = point_2[1] - point_1[1]
            #print("delta_x: {0}, delta_y: {1}".format(delta_x, delta_y))
            gradient = float(delta_y)/float(delta_x)
            #print("x: {0} point_1: [{1}, {2}] gradient: {3}".format(x, point_1[0], point_1[1], gradient))
            x_bit = x - point_1[0]
            y_bit = int(float(x_bit) * gradient)
            y = point_1[1] + y_bit
            return y

         point_i += 1




def clearScreen():
   os.system("clear")

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop = threading.Event()

    def stop(self):
        self._stop.set()

    def stopped(self):
        return self._stop.isSet()

class FanController(StoppableThread):
   """Room here for arguments to implement multigpu fan controll"""
   def __init__(self):
      super(FanController, self).__init__()
      self.daemon = True
      
   def run(self):
      self.customFanSpeed()
      
   def stop(self):
      super(FanController, self).stop()
      time.sleep(1.5)
      self.resetFan()
   
   def resetFan(self):
      print("\nReset to Auto Fan")
      process = Popen("nvidia-settings -a [gpu:0]/GPUFanControlState=0", shell=True, stdin=PIPE, stdout=PIPE)
   
   def getTemp(self):
      process = Popen("nvidia-settings -q gpucoretemp", shell=True, stdin=PIPE, stdout=PIPE)
      line_array = process.stdout.readlines()
      tmp_line = line_array[1]
      #grab number from end of line
      return int(tmp_line[-4:-2])

   def setFanSpeed(self, speed):
        #watch -n0 aticonfig --adapter=0 --od-gettemperature
        #that's the line to get ati fan speed
      process = Popen("nvidia-settings -a [gpu:0]/GPUFanControlState=1 -a [fan:0]/GPUCurrentFanSpeed={0}".format(speed), shell=True, stdin=PIPE, stdout=PIPE)
      return
   
   def customFanSpeed(self):
      """custom fan speed curve example:
         [[temp, speed],
          [temp, speed],
          [temp, speed]]
         always start at low temp/speed and head towards high temp/speed
         ensure that first point is always lower temp than possible
         ensure that gradient is always positive and less than infinity
      """
      curve_point_array = [[10, 5],
                      [20, 10],
                      [40, 15],
                      [50, 28],
                      [60, 42],
                      [66, 80],
                      [70, 99],
                      [100, 100]]

      curve = Curve(curve_point_array)


      while(not self.stopped()):
         current_temp = self.getTemp()
         new_fan_speed = curve.evaluate(current_temp)
         clearScreen()
         print("CurrTemp: {0} FanSpd: {1}".format(current_temp,new_fan_speed))
         self.setFanSpeed(new_fan_speed)

         time.sleep(1.0)
      
      #finished and ready to exit
      return


class MainThread(threading.Thread):
   def __init__(self):
      super(MainThread, self).__init__()
      self.fan_controller = FanController()
      signal.signal(signal.SIGINT, self.exit_signal_handler)
      
   def exit_signal_handler(self, signal, frame):
      self.fan_controller.stop()
        #sys.exit(0)
       
   def start(self):
      super(MainThread, self).start()
      signal.pause()
      
   def run(self):
      self.fan_controller.start()


t = MainThread()
t.start()


license: http://www.gnu.org/licenses/gpl-3.0-standalone.html
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum