Concepts / Calculating Model Parameters

Calculating Model Parameters

The program estimates a model's memory size by multiplying the total parameter count by 4, assuming each parameter is a float32 value of 4 bytes.

  • Programming

Why Count Parameters Before Training

A GPT model is defined by its configuration, and every choice in that configuration changes how many learned values the model must store. Before you commit to training a model, it helps to know how large it is. A parameter count tells you roughly how much memory the model will need, and it lets you compare one design against another.

This article approaches the topic from the code outward. You will read a short program that estimates how much memory a model's parameters occupy, and you will practice two skills. The first is counting and comparing the parameters in different modules of a transformer block, such as the feed forward module and the multi-head attention module. The second is converting a total parameter count into a size in bytes and then into megabytes. Both skills depend on one simple chain of arithmetic, so it is worth reading the program line by line before trusting any printed number.

From Parameter Count to Megabytes

The program has three calculation steps, and each one answers a different question. The first step asks how many bytes the parameters need. It assumes every parameter is a float32 number, which takes 4 bytes, so the byte count is the parameter count multiplied by 4. The second step converts bytes into megabytes. The program divides by 1024 * 1024, which is 1,048,576, rather than by one million. The third step is the print statement, which formats the megabyte value with two digits after the decimal point.

Rule

Rule

The two formulas say the same thing as the code. The variable total_size_bytes is an intermediate value, and total_size_mb is the final value that the printed line depends on. Because each step feeds the next, an error introduced early in the chain carries forward into every later value. A wrong parameter count produces a wrong byte count, and a wrong byte count produces a wrong megabyte figure, even when the conversion step itself is written correctly.

total_paramsnumber of parameterstotal_size_bytesparams times 4total_size_mbbytes divided by 1,048,576printed linetwo decimal placesmultiply by 4divide by 1024 * 1024format to 2 decimals
What sequence of transformations turns the parameter count into a byte count and then into a megabyte figure, and what value does each step hand to the next?

Predicting the Printed Size

Before you read the calculation further, make a prediction. Suppose a model has 10,000,000 parameters. Using only the two steps above (multiply by 4, then divide by 1,048,576) and the two-decimal print format, decide what number the last line will print.

What do you think happens?

What does the final line print for a model with 10,000,000 parameters?

Reveal answer
Answer:

38.15

The byte count is 10,000,000 x 4 = 40,000,000. Dividing by 1,048,576 gives about 38.147, which the two-decimal format prints as 38.15.

Worked example

Tracing the 10,000,000-parameter model

Trace total_params, total_size_bytes, and total_size_mb for a model with 10,000,000 parameters, then state the printed value.

  1. 1
    Start with the parameter count

    total_params = 10,000,000.

  2. 2
    Convert to bytes

    Each float32 parameter takes 4 bytes, so total_size_bytes = 10,000,000 x 4 = 40,000,000.

  3. 3
    Convert to megabytes

    total_size_mb = 40,000,000 / 1,048,576, which is approximately 38.147.

  4. 4
    Format the print

    Rounding to two digits after the decimal point gives 38.15.

Result

The program prints 38.15.

Dividing by the Wrong Number

  • Common mistake

    Dividing bytes by 1,000,000 to get megabytes

    What it looks like

    Using 40,000,000 / 1,000,000 for the 10,000,000-parameter model gives 40.00 instead of 38.15.

    Why it fails

    The program converts with 1024 * 1024, which is 1,048,576. Dividing by one million gives a different and incorrect result.

    Do this instead

    Divide by 1024 * 1024 so the conversion matches the program's step.

  • Common mistake

    Rechecking only the final printed line when the size looks wrong

    Why it fails

    The final value depends on every step before it, so the error may have started several steps earlier.

    Do this instead

    Inspect total_params, then total_size_bytes, then total_size_mb, in that order, and stop at the first value that breaks its expected relationship.

  • Common mistake

    Assuming a memorized parameter count for a module

    Why it fails

    The source does not list specific parameter counts for the feed forward and attention modules, so a remembered number may not match the configuration you are using.

    Do this instead

    Count the module with the same method every time and compare the computed totals.

Counting a Module with One Pattern

The word parameter refers to the stored numbers a module learns. A module's parameters() method hands back a sequence of tensors, and each tensor is a block of numbers. The numel() call measures how many individual numbers sit inside one tensor. Summing those counts over every tensor in the module gives the number of parameters that module contributes to the model.

python
Notes on the code
  • block.ff.parameters() yields every tensor in the feed forward module
  • p.numel() asks one tensor how many values it holds
  • The generator expression applies numel() to every tensor
  • The outer sum adds the answers into a single module total

Read the expression from the inside out. The part p.numel() asks one tensor how many values it holds. The generator expression applies that question to every tensor in the module. The outer sum adds the answers. The attention line has the same shape, and the only difference is which module it asks about. Because the two lines are identical except for block.ff and block.att, any disagreement between the two results must come from the module being measured, not from the counting method.

python
Notes on the code
  • The feed forward module is accessed as block.ff
  • The attention module is accessed as block.att
  • Both lines use the same counting pattern

This is why the count is a sum and not a single lookup. A module is usually made of several layers, and each layer contributes its own tensors. The loop inside the generator expression visits each of those tensors in turn, and the running total is complete only after the last one has been added. The total grows once per tensor, so when a count seems too small, check whether every tensor in the module was visited. Biases are part of the count as well, so a layer's total includes them along with its weights.

Feed Forward Versus Attention

Before running the counting code, decide which of the two modules you expect to be larger. Think about what each module does in a transformer block and what kind of weights it would need to hold. The source gives a useful benchmark: the feed forward module contains approximately twice as many parameters as the attention module. If your computed counts reverse that relationship, treat it as a sign to check the code and the configuration rather than accepting the result.

QuestionFeed forward moduleMulti-head attention module
Accessed asblock.ffblock.att
Counting expressionsum(p.numel() for p in block.ff.parameters())sum(p.numel() for p in block.att.parameters())
Source expectationApproximately twice the attention countAbout half the feed forward count
What to check if reversedModule selected, layers visited, biases includedModule selected, layers visited, biases included

The same counting method applied to both modules of a transformer block

Finding the Step That Went Wrong

When the printed size looks wrong, do not start by rechecking the final line. Inspect the intermediate values in order: total_params, then total_size_bytes, then total_size_mb. The relationships they must satisfy are simple. total_size_bytes should be exactly four times total_params, and total_size_mb should be total_size_bytes divided by 1,048,576. The first value that breaks one of these relationships marks the step where the error was introduced.

Printed size lookswrongtotal_params matchesmodule sums?total_size_bytesequals 4 xtotal_params?total_size_mb equalsbytes / 1,048,576?Printed value iscorrectFault in parametercountingFault in byteconversionFault in MBconversionstartyesnoyesnoyesno
When the final byte or MB result looks wrong, which intermediate value (parameter total, per-module count, or conversion step) is the first one that breaks the expected relationship?

The same check applies when a module count disagrees with expectation. Look at the module being measured, the counting expression, and the configuration that built the module. Because the counting expression is identical for every module, a changed result usually points to the module selected or the configuration used to build it, not to the arithmetic.

Building a Larger Configuration

Everything above used a single configuration, GPT_CONFIG_124M. That configuration is a dictionary that describes one GPT model. The same model class can produce other sizes if you give it a different dictionary, so you do not need a new class for each size. The work is in building the right dictionary. Larger GPT models are built by copying the base configuration dictionary and overriding only the size fields, such as the embedding dimension, the number of layers, and the number of heads.

python
Notes on the code
  • copy() starts from every field of the base configuration
  • Each assignment overrides one size field
  • The key names and values shown are illustrative; use the field names from your own configuration
GPT_CONFIG_124Mbase dictionaryemb_dimoverriddenn_layersoverriddenn_headsoverriddenother fieldsinherited unchangedoverrideoverrideoverridecopy
Which configuration fields are inherited unchanged from the base dictionary, and which are replaced by the override values in the new configuration?

Once the full model is built from the edited configuration, the same reporting approach is applied to the whole GPTModel. The output reports three figures: a total parameter count, a count of trainable parameters once weight tying is taken into account, and the total size of the model in megabytes. Weight tying can make the trainable count lower than the total, so the two figures are not interchangeable. The size is still derived from the total parameter count using the same 4-byte and 1,048,576 steps described earlier.

Checking Your Own Count

MEDIUM

A colleague reports that a model with 5,000,000 parameters prints 19.07 MB. Trace total_params, total_size_bytes, and total_size_mb in order, and find the first value that is wrong, or confirm that the printed value is correct.

Hints
  • The expected byte count is 5,000,000 x 4.
  • Divide the byte count by 1,048,576, not by 1,000,000.
  • Check the intermediate values in order before concluding anything about the print line.

Key Takeaways from the Calculation

  1. 1
    The program multiplies the total parameter count by 4 (float32 values are 4 bytes each) and then divides by 1024 * 1024 to report megabytes.
  2. 2
    Module counts are found by summing numel() over every tensor in parameters(), and modules must be counted with the same method, including biases, before they are compared.
  3. 3
    When a size looks wrong, trace total_params, total_size_bytes, and total_size_mb in order and fix the first value that breaks its expected relationship.
  4. 4
    Larger GPT configurations are built by copying the base dictionary and overriding only the size fields, and the full model's total and trainable counts can differ because of weight tying.

At a glance

  • The program converts a parameter count to bytes by multiplying by 4 and to megabytes by dividing by 1024 * 1024.
  • Module parameter counts are found by summing numel() over parameters(), using the same method for every module so the totals can be compared.
  • When a size result looks wrong, check total_params, total_size_bytes, and total_size_mb in order and find the first broken relationship.
  • A larger GPT configuration is created by copying the base dictionary and overriding only the size fields.

More concepts starting with C