18

How can I detect the current RAM config? I need to ask windows about if the RAM is currently running in single, dual or quad channel.

I have searched a lot, and not found any similar questions on this or other sites, which is quite surprising to me.

I'm working with C++, but this question really applies to all programming languages the same way since it's about what windows function or powershell/cmd command will give me the info I need.

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
JohnAl
  • 1,064
  • 2
  • 10
  • 18
  • Out of curiosity, do the platforms make this kind of information available? In embedded systems, we have to rely on the platform schematics. – Thomas Matthews Apr 03 '18 at 15:05
  • 2
    Is this a starting point? https://msdn.microsoft.com/en-us/library/aa394347(v=vs.85).aspx WMI seems the right section: https://msdn.microsoft.com/en-us/library/aa394582(v=vs.85).aspx – Richard Critten Apr 03 '18 at 15:08
  • CPU-Z is able to correctly detect the channel config of the RAM, so if that software can detect it on windows, my software should most likely also be able to. – JohnAl Apr 03 '18 at 15:08
  • Well...if it is about all programming languages then the question should be tagged `Language-Agnostic` not with specific languages. In reality though it sounds like you want a C++ answer which would be different than a Powershell answer and most likely not even possible in CMD. – EBGreen Apr 03 '18 at 15:09
  • @RichardCritten I have looked at that Win32_PhysicalMemory before, but as far as I can tell none of the data in there helps me with detecting the channel config – JohnAl Apr 03 '18 at 15:09
  • Why do you need to know/care? – Jesper Juhl Apr 03 '18 at 15:11
  • @EBGreen I'm fine with everything, calling a windows function from c++ or using powershell/cmd from C++ same like you could use it from every other language. Just need to know how to get the correct data from windows. – JohnAl Apr 03 '18 at 15:11
  • @EBGreen I have removed the cmd tag and added the language-agnostic tag, thanks for making me aware of that! – JohnAl Apr 03 '18 at 15:16
  • @JesperJuhl My application needs to warn the user when an incorrect ram config (single channel) is detected, because that's not supported by the application and results in very bad performance. – JohnAl Apr 03 '18 at 15:18
  • C++ is designed for abstract hardware. If there are such interfaces on Windows then the MSDN has got you covered. – Ron Apr 03 '18 at 15:18
  • 1
    You can use the `Win32_PhysicalMemory` wmi class and access the `DeviceLocator` member to figure out which DIMM slot RAM is installed in. – Maximilian Burszley Apr 03 '18 at 15:19
  • @TheIncorrigible1 I have looked at that data for 2 different PCs, and for one it's giving me data like DIMM_A1, DIMM_B1, DIMM_C1 and for the other PC it's giving me data like XMM1, XMM3, XMM4. That makes me think the names for the DeviceLocator vary greatly depending on what RAM or platform you use, and that makes it very hard or impossible to interpret in a good way. – JohnAl Apr 03 '18 at 15:24
  • The `FormFactor` or `MemoryType` member will tell you what you're working with. – Maximilian Burszley Apr 03 '18 at 15:36
  • Alternatively, check out [`InterleavePosition`](https://msdn.microsoft.com/en-us/library/aa394347(v=vs.85).aspx) – Maximilian Burszley Apr 03 '18 at 15:38
  • @TheIncorrigible1 I have tested 3 different PCs now, two dual channel and one quad channel. `FormFactor` is always `8` for all RAM modules, no matter if DDR3, DDR4, dual channel or quad channel. So it does not seem to hold any relevant value, it's just always 8. `Memory Type` is `0` for one quad channel system and `0` for one dual channel system, and `24` for the other dual channel system. `InterleavePosition` actually has no value at all on one of the systems, so using that also doesn't seem to work. On the other two systems it's `0,0,0,0` (quad channel) and `2,2,2` (dual channel) – JohnAl Apr 03 '18 at 15:45

2 Answers2

6

InterleavePosition is what you're looking for though. One came up as 2,2,2 because it's running 3 sticks in dual channel. What you need to find out is how to identify a machine running single-channel so that you can use the output of this command:

wmic memorychip get InterleavePosition

Edit: Actually not sure about the dual channel with 3 sticks. Some research suggests most motherboard nowadays will make the odd one out single channel.

So from the MSDN, this is what we have to work with in terms of digging up system info about interleaved memory.

Position of the physical memory in an interleave. For example, in a 2:1 interleave, a value of "1" indicates that the memory is in the "even" position.

This property is inherited from CIM_PhysicalMemory.

0 - Noninterleaved

1 - First position

2 - Second position

Plus InterleaveDataDepth which says this:

InterleaveDataDepth

Unsigned 16-bit integer maximum number of consecutive rows of data that are accessed in a single interleaved transfer from the memory device. If the value is 0 (zero), the memory is not interleaved.

Mind you, interleave is a fancy word for "share mutually" which is similar to multi-channel nowadays but it's not the same thing. From wiki on interleaved memory:

It is different from multi-channel memory architectures, primarily as interleaved memory is not adding more channels between the main memory and the memory controller. However, channel interleaving is also possible...[]

Using this, I'll share what it looks like to have 4 RAM sticks in dual channel using cmd.exe:

example of dual channel memory output from wmic

Edit: Several people have confirmed these values work just fine on some machines but too often return puzzling/nonsense values.

Dylan Moore
  • 443
  • 4
  • 14
  • 1
    Just pointing out `wmic` is `C:\Windows\System32\wbem\WMIC.exe` – Maximilian Burszley Apr 03 '18 at 15:56
  • 1
    I have tested one single channel PC now, and there the output of InterleavePosition is `0`. How should I interpret that data? In the case of 1 single ram module its easy to know its definitely single channel, but two ram modules running single channel will most likely say `0,0` or `2,2`, so how would I detect the amount of channels from that? – JohnAl Apr 03 '18 at 16:01
  • 1
    My edits about the Interleave info from MSDN should help but if it says `0` in InterleaveDataDepth, it's non-interleaved meaning single-channel. – Dylan Moore Apr 03 '18 at 16:02
  • 1
    I will also point out that InterleavePosition is empty on my machine. So like many hardware classes in WMI, this will be dependent on the manufacturer actually writing the info to WMI in the first place. – EBGreen Apr 03 '18 at 16:04
  • Yeah, using `InterleaveDataDepth` should always work. If there are no consecutive rows of data being accessed in the RAM, there is single channel RAM. – Dylan Moore Apr 03 '18 at 16:05
  • `InterleaveDataDepth` is also empty on one of the PCs I tested with – JohnAl Apr 03 '18 at 16:07
  • Hmm. That could take us down another rabbit hole. It's a small possibility this is normal behavior under some circumstances, what kind of RAM config do you know that machine to have? – Dylan Moore Apr 03 '18 at 16:08
  • `InterleaveDataDepth` says `0,0,0,0` for me in quad channel config, same like `InterleavePosition` which is also `0,0,0,0`. How does that make sense? – JohnAl Apr 03 '18 at 16:09
  • @DylanMoore the PC where both `InterleaveDataDepth` and `InterleavePosition` are empty is a PC with an `i7 4770` – JohnAl Apr 03 '18 at 16:10
  • Can confirm using my Surface laptop that it shows up blank for both `Interleave` attributes often enough to present a challenge. It looks like these wmic datapoints are nonsense for the most part. – Dylan Moore Apr 03 '18 at 16:11
  • And I have not yet encountered a PC where CPU-Z can't tell if it's single, dual or quad channel config, so they most likely have to have a better more accurate way to query windows for the info? – JohnAl Apr 03 '18 at 16:15
  • Yes, but their SDK is pricey. – Dylan Moore Apr 03 '18 at 16:15
  • I don't want to use their SDK, I just mean they also just have to ask windows about the data. If CPU-Z can get it, every software running on windows should be able to get it. – JohnAl Apr 03 '18 at 16:17
  • 3
    @JohnAl: It's not true that CPU-Z just "asks Windows". Of course it uses Windows APIs to fetch the data, but it may be fetching raw binary firmware tables and then interpreting the contents itself. So there may not be any Windows API to perform this interpretation. – Ben Voigt Apr 03 '18 at 16:21
  • CPU-Z correctly identifies my memory as hexa channel, but `wmic` shows InterleaveDataDepth = 3 for all 12 sticks, and InterleavePosition is labeled 1,2,3,1,2,3,1,2,3,1,2,3 – Elliott B Aug 19 '20 at 06:52
2

Look at the SMBIOS specifications: System Management BIOS (SMBIOS) Reference Specification. Actually, latest version is dated 14 May 2018.

Step 1: You need to read the Current Interleave from 7.6 Memory Controller Information (Type 5) for older versions, and then follow the notes about how to read the newest structures.

Step 2: You need to get the memory devices from:

7.38 Memory Channel (Type 37)
Offset Name                   Length Value  Description
 06h   Memory Device Count(n)  BYTE  Varies Number of Memory Devices (Type 11h) that are 
                                            associated with this channel
                                            This value also defines the  number of 
                                            Load/Handle pairs that follow. 

You should read that Count(n) memory devices with their associated channels.

Step 3: all together, You will end up with a table as follows:

Channel 1: DIMM #0
Channel 1: DIMM #1
Channel 2: DIMM #0
Channel 2: DIMM #1

Luckily, in the SMBIOS specifications there are some examples.

For instance look at section 7.7.3 Memory subsystem:

04h ; 2-way interleave currently used

As the specifications are frequently subject to change and some are obsolete, I wouldn't rely on any out-of-the-box Windows WMI/API. The best way I can suggest You, is to read the RAW SMBIOS DATA in one shot and build a simple table like the one above. Here is how: SMBIOS Demystified

Moreover, I believe You can't do any further assumption about the real effective channel speed. You may need to gather some othe information about the speed of each DIMM module.

IMHO, posting the source code for such a task goes far beyond the current question scope, so there are some links: the best reference about that topic is dmidecode but, as I feel good with Delphi, I would prefer to look at this Delphi/FPC post: Reading the SMBios Tables using Delphi.

deblocker
  • 7,629
  • 2
  • 24
  • 59