• Welcome to TechPowerUp Forums, Guest! Please check out our forum guidelines for info related to our community.
  • The forums have been upgraded with support for dark mode. By default it will follow the setting on your system/browser. You may override it by scrolling to the end of the page and clicking the gears icon.

GPU-Z Shared Memory Class in C#

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.07/day)
Location
Cheeseland (Wisconsin, USA)
I wrote a C# class that reads the shared memory from GPU-Z.
It doesn't use DLLImport or PInvoke (but it does require .Net 4), as it uses the new MemoryMappedFiles (MMF) namespace they added in 4.0

The problem is that I can't think of anything useful to do with it that I can't get from just running GPU-Z. :/

Any thought fellow coders and users of GPU-Z?

I'll happily post the class source code when I nail down all the output requirements needed for any ideas you gents (and ladies) throw out.
 
Graph clockspeeds and memory usage.
 
134 views and only one suggestion? (Thanks Ford)
You guys suck at ideas as much as I do. :laugh:
 
Yea.. I'm drawing blanks.. Oh course I've not had my full dose of caffeine yet... But I'm working on it...lol but right now.. I got nothing... :p
 
I could always just toss the class code out and let people play with it.
I just wanted to get some ideas what output formats (Arrays, Lists, etc.) might be useful for others and add them as methods to the class.

Curently what I have is ..
Code:
void ReadSharedMemory() // Reads data from shared mem into classes
List<KeyValuePair<string, string>> GetListOfRecords(); // Return a list of GPUZ_RECORD
KeyValuePair<string, string>[] GetArrayOfRecords(); // Returns an array of GPUZ_RECORD

List<GPUZ_SENSOR_RECORD> GetListOfSensors(); // Returns list of the sensor records.
GPUZ_SENSOR_RECORD[] GetArrayOfSensors(); // Returns an array of sensor records.

KeyValuePair<string, string> GetRecordByName (string name);
GPUZ_SENSOR_RECORD GetSensorByName (string name);

KeyValuePair<string, string> GetRecordByIndex (int index);
GPUZ_SENSOR_RECORD GetSensorByIndex (int index);

Anyone want to run a quick test on this stub program for me?
Launch program, hit button. See if records print out (no sensor records, just board records)
Try with GPU-Z running and not (It should detect if GPU-Z is running).
You need .Net 4

Thanks !!
 

Attachments

Last edited:
Without GPU-Z running:
withoutgpuz.jpg



With GPU-Z Running:

withgpuz.jpg
 
Not running:

Not.png


Running:

Not running.png
 
Thanks kids !!
Munki sent me a PM pointing out my incorrect use of "it's" instead of "its" in the error message.
Please feel free to trash me if you are a grammar nazi. :laugh: (it's been corrected in the code)

If someone could try running it on a 32-bit box I would appreciate it. No need for screens, just let me know if you encounter any problems.

@TissueBox : Welcome to P&W, our little corner of the world. Are you a coder?
 
Thanks kids !!
Munki sent me a PM pointing out my incorrect use of "it's" instead of "its" in the error message.
Please feel free to trash me if you are a grammar nazi. :laugh: (it's been corrected in the code)

If someone could try running it on a 32-bit box I would appreciate it. No need for screens, just let me know if you encounter any problems.

@TissueBox : Welcome to P&W, our little corner of the world. Are you a coder?

:laugh::laugh::laugh::laugh: I'm far from a grammar Nazi. I was born and raised in Georgia, my grammar is horrid :laugh:
 
Sorry Munki ... I meant to say "if y'all a grammar nazi" :roll:

I coded the class in a separate class file and removed the MessageBox error.
I replaced it with an accessor (property called GPUZ_Running) so you can handle the fact GPU-Z may not be running yourself.

Code:
GPUZ_SHMEM shMem = new GPUZ_SHMEM();
if (!shMem.GPUZ_Running)
{
    // handle it however you want
}
else shMem.ReadSharedMem();

Here's the class code if anyone want to take a look ...
PHP:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.IO;
using System.IO.MemoryMappedFiles;

namespace WindowsFormsApplication1
{
    public class GPUZ_SHMEM
    {
        private const int MAX_RECORDS = 128;
        private bool gPUZ_Running = false;

        public class GPUZ_SENSOR_RECORD
        {
            public string name;
            public string unit;
            public UInt32 digits;
            public Double value;
        };

        public class GPUZ_SH_MEM
        {
            public UInt32 version;
            public volatile Int32 busy;
            public UInt32 lastUpdate;
            public List<KeyValuePair<string, string>> data = new List<KeyValuePair<string, string>>(MAX_RECORDS);
            public List<GPUZ_SENSOR_RECORD> sensors = new List<GPUZ_SENSOR_RECORD>(MAX_RECORDS);
        };

        public GPUZ_SH_MEM shMem = new GPUZ_SH_MEM();

        public GPUZ_SHMEM()
        {
            // Check to see if GPU-Z is running.
            foreach (Process p in Process.GetProcesses())
            {
                if (p.ProcessName.Contains("GPU-Z")) gPUZ_Running = true;
            }
        }

        public bool GPUZ_Running { get { return gPUZ_Running; } }

        public void ReadSharedMemory()
        {

            string key, value;
            string name, unit;

            using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("GPUZShMem"))
            {
                using (MemoryMappedViewStream mmvs = mmf.CreateViewStream())
                {
                    BinaryReader reader = new BinaryReader(mmvs, Encoding.Unicode);

                    shMem.version = reader.ReadUInt32();
                    shMem.busy = reader.ReadInt32();
                    shMem.lastUpdate = reader.ReadUInt32();

                    for (int i = 0; i < MAX_RECORDS; i++)
                    {
                        // Remove any null values in the key array
                        key = new string(reader.ReadChars(256)).Trim('\0');
                        if (key.Contains("\0")) key = key.Substring(0, key.IndexOf("\0"));

                        // Remove any null values in the value array
                        value = new string(reader.ReadChars(256)).Trim('\0');
                        if (value.Contains("\0")) value = value.Substring(0, value.IndexOf("\0"));

                        // Only add List item if there is a valid key
                        if (key != String.Empty)
                        {
                            KeyValuePair<string, string> dataItem = new KeyValuePair<string, string>(key, value);
                            shMem.data.Add(dataItem);
                        }
                    }

                    for (int i = 0; i < MAX_RECORDS; i++)
                    {
                        // Remove any null values in the name array
                        name = new string(reader.ReadChars(256)).Trim('\0');
                        if (name.Contains("\0")) name = name.Substring(0, name.IndexOf("\0"));

                        // Remove any null values in the unit array
                        unit = new string(reader.ReadChars(8)).Trim('\0');
                        if (unit.Contains("\0")) unit = unit.Substring(0, unit.IndexOf('\0'));

                        // Only add List item if there is a valid name
                        if (name != String.Empty)
                        {
                            GPUZ_SENSOR_RECORD sensorItem = new GPUZ_SENSOR_RECORD();
                            sensorItem.name = name;
                            sensorItem.unit = unit;
                            sensorItem.digits = reader.ReadUInt32();
                            sensorItem.value = reader.ReadDouble();

                            shMem.sensors.Add(sensorItem);
                        }
                    }
                }
            }
        }

        public List<KeyValuePair<string, string>> GetListOfRecords()
        {
            return shMem.data;
        }

        public KeyValuePair<string, string>[] GetArrayOfRecords()
        {
            KeyValuePair<string, string>[] kvpArray;
            return kvpArray = shMem.data.ToArray();
        }

        public List<GPUZ_SENSOR_RECORD> GetListOfSensors()
        {
            return shMem.sensors;
        }

        public GPUZ_SENSOR_RECORD[] GetArrayOfSensors()
        {
            GPUZ_SENSOR_RECORD[] sensorArrray;
            return sensorArrray = shMem.sensors.ToArray();
        }

        public KeyValuePair<string, string> GetRecordByName(string name)
        {
            foreach (KeyValuePair<string, string> k in shMem.data)
            {
                if (k.Key == name) return k;
            }

            // REturn a KVP with null values if name not found
            return new KeyValuePair<string, string>(null, null);
        }

        public GPUZ_SENSOR_RECORD GetSensorByName(string name)
        {
            foreach (GPUZ_SENSOR_RECORD r in shMem.sensors)
            {
                if (r.name == name) return r;
            }

            // Return a null class value if name not found
            return null;
        }

        public KeyValuePair<string, string> GetRecordByIndex(int index)
        {
            if (index >= 0 && index < shMem.data.Count) return shMem.data[index];
            else return new KeyValuePair<string, string>(null, null);

            // Returns a KVP with null values if index out of range
        }

        public GPUZ_SENSOR_RECORD GetSensorByIndex(int index)
        {
            if (index >= 0 && index < shMem.sensors.Count) return shMem.sensors[index];
            else return null;

            // Returns a null class value if index out of range.
        }
    }
}

It's C# code, I just used the php tags to give it a little color. :)
As always, comments and suggestions appreciated !
 
Last edited:
@TissueBox : Welcome to P&W, our little corner of the world. Are you a coder?

Unfortunately, I am not - I'm more of a guinea pig :laugh:

Looked at the "New Forum Posts" and decided to contribute something here :toast:
 
hmm any chance you could set it to record and log memory usage kinda like fraps maybe? log min max avg memory usage i dont know lol maybe GPU-Z does that? i dont know drawing blanks just saying random shit that comes to mind
 
Can GPU-Z run silently or minimized on start? If that can be done you could use the C# application to launch and close GPU-Z as needed.
 
The problem is that I can't think of anything useful to do with it that I can't get from just running GPU-Z. :/

Any thought fellow coders and users of GPU-Z?

Idea! How 'bout such feature: "alert me if some monitored value goes above/beyond *value* and/or stays above/beyond *value* for more than *time interval*." ?
As far as I remember, GPU-Z can't do that.
 
Last edited:
hmm any chance you could set it to record and log memory usage kinda like fraps maybe? log min max avg memory usage i dont know lol maybe GPU-Z does that? i dont know drawing blanks just saying random shit that comes to mind

GPU-Z can log everything if you check the log to file CheckBox. It puts it in a CSV text file.

Can GPU-Z run silently or minimized on start? If that can be done you could use the C# application to launch and close GPU-Z as needed.

You can start GPU-Z minimized by going into the shortcuts properties and set the run dropdown to minimized. It would be a simple thing to launch GPU-Z from any app.

Idea! How 'bout such feature: "alert me if some monitored value goes above/beyond *value* and/or stays above/beyond *value* for more than *time interval*." ?
As far as I remember, GPU-Z can't do that.

That's a thought. A little, light wieght temp alarm utility. Any thoughts on how long it should read a "high" temp before alerting?

One of the current issues is that if you open two instances of GPU-Z (say for crossfired cards) it still writes the data to the same shared memory and it's kind of hit or miss what card readings you are going to get. Maybe one of these days W1zz will add full multi-GPU functionality to GPU-Z
 
Last edited:
Any thoughts on how long it should read a "high" temp before alerting?

I would suggest two modes:
Monitor a user requested reading, with the ability to choose to trigger when going either below or above a user supplied value.
First mode: alert as soon as it is below/above the threshold.
Second mode: alert after it stays above/below the threshold longer than an interval which is also supplied by the user.
When monitoring more than one thing, the modes should be set "per rule". for example, with two rules: "alert if the GPU temp stays above 75°C for more than 300 seconds & alert immediately, if it goes above 90°"
or "immediately alert if the Vcore goes above 1.35V & alert if the GPU temp stays above 80°C for more than 60 seconds" and so on...

P.S. The "below" setting could be useful, for example, to spot a fan failure.
 
Last edited:
Another Stub

Here's another test stub.
It's should read the GPU Temp (only, not #1 - #3) for a single card or a crossfire pair.
You need to have two instances of GPU-Z running if using more than one card (and of course not have both instances pointing at the same card :D )
It reads the shared mem every 500ms (this is somewhat problematic as it's still a bit of a crap shoot what card will be in the shared mem slot).

Anyone have a dual-GPU card they could try it on?

EDIT : No error checking to see if GPU-Z is running. It will throw an exception if no GPU-Z is available.

Thanks !
 

Attachments

well i was thinking more like if the card switches to 3D clocks then have it record memory usage,

GPU-Z tends to record constant makes it harder to pinpoint where Memory usage spikes im just being nitpicky tho as it would help pinpoint some of the harsher areas to test in games etc.

Still pretty cool stuff your doing here Kreij
 
I assume you mean memory on the GPU?
I have to look into this as only one of my corssfired cards shows dedicated and dynamic memory usage. Does the memory usage show up if you only have one card in?

I'm just throwing out little test programs right now to get a handle on what I can and cannot do with the shared memory.
 
its no problem Kreij
and yea i ment Vram usage,

example i dont care what vram usage is when lvl is loading in BF3 for instance, as my GPU clocks are idle at the time, same goes for SHogun 2 it takes 5-6 mins to load a battle, so if it could trigger logging ONLY during 3D clocks it would be amazing as aka run a benchmark we know how long it is, can use fraps for instance to test frame rates but at the same time, i can log just 3D vram usage on a second by second basis, might be way to hard to do, just something i find interesting.

im only running 1 card right now and GPU-Z seems to be reporting memory usage properly
 
I've made an overlay info display (small but practical) to run over a game or app on a corner of the screen.
I can have realtime info of my gpu without leaving the game.

Just an ideia..
 
Here's another test stub.
It's should read the GPU Temp (only, not #1 - #3) for a single card or a crossfire pair.
You need to have two instances of GPU-Z running if using more than one card (and of course not have both instances pointing at the same card :D )
It reads the shared mem every 500ms (this is somewhat problematic as it's still a bit of a crap shoot what card will be in the shared mem slot).

Anyone have a dual-GPU card they could try it on?

EDIT : No error checking to see if GPU-Z is running. It will throw an exception if no GPU-Z is available.

Thanks !

So, I finally got some time to relax from my studies, so I booted up window$.
I checked how is that utility working... it doesn't look too well - monitors the max GPU clock reached.

Yet, it looks promising, if ever going to be completed ;]

I attached a screenshot:
gpu-z_read.png
 
LOL ... didn't do that before. Something must have changed in 0.6.2

I've put this project on hold at the moment.
It's really unreliable for reading two cards, unfortunately. I'm hoping W1zz decides to add mutli-card support to the shared mem one of these days.
 
Last edited:
I noticed the NVIDIA Quadro driver (version 29#) had an option to install a WMI library. Has anyone taken a look into that?
 
Hello!

Please tell me why do we have to deal with GPU-Z and SharedMem interface? Why don't just read sensors as GPU-Z does? Is there GPU-Z source code? Or source code for reading sensors?

I'm not familiar with this stuff (sensors reading) hence such a question I asked.

Thanks.

Paul
 
Back
Top