Skip to main content

Command Palette

Search for a command to run...

From Research to Production: The Benchmark Said 15 FPS. My Environment Said 10. Dependency Versions Said Nothing. πŸ˜‘

Updated
β€’5 min read
From Research to Production: The Benchmark Said 15 FPS. My Environment Said 10. Dependency Versions Said Nothing. πŸ˜‘
N
I build AI products from every angle β€” model development, cloud platform, architecture, and engineering leadership.

In my previous post, I wrote about bridging the gap between research code and production systems.

This one is about something I did not pay enough attention to β€” until I had to. πŸ˜…

Library versions. Yes, really. Stay with me. πŸ™


I once received a codebase from a PoC engineer who had genuinely done great work.

The model was accurate, the approach was validated, and they had benchmarked inference at 15 FPS on their GPU server.

For our use case β€” a real-time system where both speed and accuracy were hard requirements β€” that number was exactly what we needed.

So I set everything up. Same input file, same configuration, same model weights. Did everything right. Felt very professional about it.

Ran it.

"Excuse me, what?" My disappointment was immeasurable and my day was ruined. πŸš‘ πŸš‘ πŸš‘ πŸš‘

10 FPS. 😱😱😱


Basic confirmation Before panicking, I did the responsible thing and checked everything I could think of.

So I did what any reasonable engineer does β€” I assumed I had done something wrong and started checking everything again. πŸ€” Twice. Maybe three times. I am not counting.

  • Same input.

  • Same config.

  • Same weights.

Still 10 FPS. 😱

The environment was committed to its choices. Not mine. πŸ₯Ή


Profiling the main code blocks When the obvious checks give you nothing, you go deeper. So I did.

So I started profiling. Pre-processing, inference, post-processing β€” one by one.

The inference timing was clearly off.

And after a while β€” longer than I would like to admit, and we will leave it at that β€” I found it.


Dependency Inconsistency 😱 Spoiler: the code was fine. The libraries had simply decided to live their own lives.

The library versions were different. Not one library. Several:

  • numpy

  • torch

  • torchvision

  • opencv-python

And the tricky part was that there were three different version states all quietly existing at the same time:

  • Their actual server environment used for benchmarking

  • Their requirements.txt in the repository

  • The environment I had built from that file β€” and before you ask, yes, I built it from the requirements.txt. Turns out that is not always enough. πŸ₯Ή

None of them fully matched each other. Living their own lives. Unbothered.

Honestly, who would think that library versions could eat 33% of your speed?

Not me. Not that day.

Same code. Same model. Same hardware. Just a few version numbers sitting quietly in a text file, minding their own business, and taking a third of my performance with them. πŸ˜‘

Nobody made a mistake. This is just what happens.


How Does This Even Happen?
Nobody changed anything. And yet, everything was slightly different.

When versions are not strictly pinned, pip installs what it considers compatible β€” not necessarily what was originally running.

For example, instead of:

torch==2.0.0
numpy==1.24.0

A requirements.txt with loose ranges like:

torch>=1.0
numpy>=1.0

...gives pip a lot of room to decide. And different machines, different times, different existing packages β€” pip may land on different versions each time.

It gets more interesting from there. Even with the same Python package versions, these can still push your environment in a different direction:

  • Loose version ranges β€” pip picks what fits, not what you had

  • Missing lock files β€” no single source of truth for exact versions

  • CUDA wheel differences β€” torch==2.0.0 installed with CUDA 11.8 and torch==2.0.0 installed with CUDA 12.1 are different wheels β€” pinning the version alone is not enough

  • Driver versions β€” same package, different runtime behavior

  • OS differences β€” compiled packages like opencv-python can behave differently across Ubuntu versions

The reason it is easy to miss is that nothing breaks loudly.

The model runs. The results look correct. The gap shows up in performance β€” and in a real-time system, performance is the product. Same code, different versions. Rude, honestly. πŸ˜‚

When I finally asked them to share what was actually installed on their server β€” not what the requirements.txt said, but the real live environment β€” everything became clear.

The file had captured their intention, not their reality.


What to check when the numbers don't match
If you find yourself in the same situation, here is where to start before going down a long debugging rabbit hole. πŸ‡

Check these three places first:

  • The original environment β€” ask the engineer to run pip freeze on their actual server.

  • The requirements.txt β€” compare it against the actual environment. They should be the same. Sometimes they are not, and that is okay, but you need to know.

  • Your own environment β€” run pip freeze yourself and compare. All three should tell the same story.

If any of them disagree, that is your starting point.

One command that makes all of this much easier β€” run it on the same day you run your benchmark, on the same server:

pip freeze > requirements.txt

That number you are reporting β€” 15 FPS, 200ms latency, whatever it is β€” deserves to have its environment captured alongside it.

Future you, and whoever receives your code next, will be very grateful. πŸ™


Been there. Survived it.

Now I run pip freeze like it is part of my morning routine. Coffee, pip freeze, then start the day. β˜•

Is that paranoid? Perhaps. But 15 FPS is 15 FPS. πŸ˜„