You are not logged in.

#1 2021-09-21 17:15:15

kokoko3k
Member
Registered: 2008-11-14
Posts: 2,390

[SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

Hello,
for whatever reason, the value of /sys/class/drm/card1/device/gpu_busy_percent is not very stable in some circumstances (DXVK is problematic, while glxgears or vkcube are fine, go figure why)
I think the tool radeontop is able to give good results by sampling that value multiple times, and i'd like to do the same in a script.
By now, i'm able to get a moving average through awk with the following, where N is the window size:

BEGIN { N=30 }

{
  s+=array[i++]=$1

  if (i>=N) i=0
}

NR>=N {
        print s/N
        s-=array[i]
}

Now i need to feed it in an efficient way, and i'm a bit lost because i'm not that good in using read in loops, and I don't even know if that would be the right way.
I need something like: keep_echoing(/sys/class/drm/card1/device/gpu_busy_percent) | awk -f /tmp/avg.awk

Any hint, please?

Thanks!

Last edited by kokoko3k (2021-09-22 12:28:20)


Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !

Offline

#2 2021-09-21 20:42:41

seth
Member
Registered: 2012-09-03
Posts: 49,992

Re: [SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

awk -f… < <(while true; do read line; echo "$line"; sleep 5; done < /sys/class/drm/card1/device/gpu_busy_percent)

Instead of the external sleep, you can use https://blog.dhampir.no/content/sleepin … ep-forever
"echo" and "read" should™ be internal functions for bash/zsh - maybe "print" is more useful.
bash/zsh do have arithmetic routines ((++i)), so technically you don't need awk either

Edit, linked script is way to complicated.

snore(){ [ -z "$1" ] && read /dev/null || read -t "$1" /dev/null }

and you can just "read -t 5 /dev/null" instead of sleeping.

(Now waiting for eschwartz to explain why stalling on reading /dev/null is bad ;-)

Edit #2: at least zsh doesn't like the ":+-t" parameter substitution and read omits the "t"… somehow

Last edited by seth (2021-09-21 21:10:18)

Offline

#3 2021-09-22 11:11:32

kokoko3k
Member
Registered: 2008-11-14
Posts: 2,390

Re: [SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

Thanks seth, for some reason it just print the first value.
temporally i've no access to that machine, but i'm testing with /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
This is what i get:

koko@Gozer# awk -f /tmp/avg.awk < <(while true; do read line; echo "$line"; sleep 0.1; done < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
52583.4
0
0
0
..
0
^C

See also:

while true; do read line; echo "$line"; sleep 0.1; done < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
koko@Gozer# while true; do read line; echo "$line"; sleep 0.1; done < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
1317826



^C

-EDIT
seems to work this way:

awk -f /tmp/avg.awk < <(while true ; do read line < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ; echo $line ; sleep 0.1 ; done)

(Now waiting for eschwartz to explain why stalling on reading /dev/null is bad ;-)

Why not just read from stdin, it works:

awk -f /tmp/avg.awk < <(while true ; do read line < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ; echo $line ; read -t 0.1 ; done)

Last edited by kokoko3k (2021-09-22 11:24:05)


Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !

Offline

#4 2021-09-22 12:54:55

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,449
Website

Re: [SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static int *values;
static int nsamples = 0;
static double timeout = 1.0;
static const char *fname;

int loop(int i, int count) {
	FILE *fp = fopen(fname, "r");
	int sum, j;
	fscanf(fp, "%d", &values[i]);
	fclose(fp);
	for (j = 0, sum = 0; j < count; j++) sum += values[j];
	printf("%0.2lf\n", sum / (double) count);
	usleep(1000000 * timeout);
}

int main(int argc, const char *argv[]) {
	if (argc != 4 || access(argv[3], R_OK) != 0) {
		fprintf(stderr, "Usage: %s <loop-duration> <n-samples> <filename>\n", argv[0]);
		return 1;
	}
	timeout = atof(argv[1]);
	nsamples = atoi(argv[2]);
	fname = argv[3];
	if (timeout < 0) timeout = 1.0;
	if (nsamples < 0) nsamples = 5;
	values = malloc(nsamples * sizeof(int));
	int i;
	for (i = 0; i < nsamples; i++) loop(i, i+1);
	while (1) for (i = 0; i < nsamples; i++) loop(i, nsamples);
	return 0;
}

Last edited by Trilby (2021-09-22 13:04:00)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2021-09-22 14:10:08

seth
Member
Registered: 2012-09-03
Posts: 49,992

Re: [SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

seems to work this way

Seems the driver doesn't write data while the device is open sad

Why not just read from stdin

Because the moment any input appears on stdin the read command succeeds and terminates (before the timeout) - you want a dead source that's not gonna read ever.

Offline

#6 2021-09-22 14:16:26

kokoko3k
Member
Registered: 2008-11-14
Posts: 2,390

Re: [SOLVED] Get a moving average of /sys/../device/gpu_busy_percent

Thanks Trillby, that is of course more efficient,
I've partially modified it to be more useful for my need:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static int *values;
static int nsamples = 0;
static double timeout = 1.0;
static const char *fname, *foutname;

int loop(int i, int count) {
	FILE *fp = fopen(fname, "r");
	unsigned long int sum; 
	int j;
	fscanf(fp, "%d", &values[i]);
	fclose(fp);
	for (j = 0, sum = 0; j < count; j++) sum += values[j];
	double avg =  sum / (double) count;
	printf("%0.2lf\n", avg); //print continuosly
	//...but dump to a file everytime we start to fill a new window:
	if (i == 0 ) {
		FILE *fpout = fopen(foutname,"w");	
		fprintf(fpout, "%f", avg );//writing data into file  
		fclose(fpout);
	}
	usleep(1000000 * timeout);
}

int main(int argc, const char *argv[]) {
	if (argc != 5 || access(argv[3], R_OK) != 0) {
		fprintf(stderr, "Samples values from \"filename-input\" at rate \"samples-per-second\" and smooth them over a moving window sized \"window-size\"\n");
		fprintf(stderr, "dump continuosly on screen and less frequently to \"filename-output\"\n\n");
		fprintf(stderr, "Usage: %s <samples-per-second> <window-size> <filename-input> <filename-output>\n", argv[0]);
		return 1;
	}
	timeout = 1/atof(argv[1]);
	nsamples = atoi(argv[2]);
	fname = argv[3];
	foutname = argv[4];
	if (timeout < 0) timeout = 1.0;
	if (nsamples < 0) nsamples = 5;
	values = malloc(nsamples * sizeof(int));
	int i;
	for (i = 0; i < nsamples; i++) loop(i, i+1);
	while (1) for (i = 0; i < nsamples; i++) loop(i, nsamples);
	return 0;
}

Thank you seth, i learned how to use read and redirections with loops, finally.

Last edited by kokoko3k (2021-09-22 15:36:32)


Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !

Offline

Board footer

Powered by FluxBB