AI@Home – DeepSeek R1 8B

Conditions & context


Today we are poking needles into DeepSeek R1 8B AI model, specifically the 0528 update, which is based on Qwen3 8B model. Since I have an 16GB card I’ve picked the 8-bit variant. Spoiler alert! This model would give Dostoyevsky and Tolstoy run for their money! :-)

As in all my tests, I use the same prompt, the same hardware, and the same methodology. I’m looking at the same set of metrics across every model: VRAM usage, GPU utilization, CPU load, token throughput, tokens written, and total response time. These matter to me because they reveal whether a model is actually usable on consumer hardware — not just in theory, but in practice.

SpecsValue
Linux DistroUbuntu Server 24.04.4 LTS
Linux Kernel6.8.0-101
CPUIntel CORE i7 14th Gen 14700K Cores: 8P/12E Threads: 28
MotherboardMSI PRO B660M-A
RAM80 GB DDR4 (32+16+32+16)
SSDCrucial NVME 1TB
GPUMSI NVidia GeForce RTX 5060Ti Shadow 2X OC PCIe 5.0×8
CUDA Cores4,608
VRAM16 GB GDDR7 128-bit 448 GB/s
GPU DriverNVidia 590.48.01
CUDA version13.1
Ollama version0.17.4
ModelDeepSeek R1 8B 0528
QuantizationQ8

The prompt

Write a simple Python function that checks if a number is prime.
Explain how it works in plain English, like you're teaching
a beginner.
The results


DeepSeek R1 is a reasoning model — meaning before it gives an answer, it thinks and debates itself, second-guesses its own logic, before it responds. Similar to Copilot’s Real Talk mode.

Watching the escalating progression of this model’s thinking was so riveting I pasted it below for you to see the vast difference between its 1st and 4th reply to an identical prompt.

Unlike my prior tests this is an 8-bit model, so although it has only 8 billion parameters it was weighed down by higher accuracy of reasoning, and clocked at speeds where 12-14B models normally are on my hardware — it was half the speed of the other 8B models I’ve tried so far.

What made this test unique was the progression across the runs. I wanted to see, if this was a trend and did an additional (4th) run just to be sure. And it was apparent that as the conversation context was accumulating so were the tokens the model carried over. Mind you, all I did was paste the above prompt into the chat window 4 times in a succession. That was all I did.

ModelQuantRunTokens/secTotal Time (s)Tokens WrittenVRAM (GB)GPU Util
DeepSeek R1 8BQ8148.2513s6179.698%
DeepSeek R1 8BQ8247.8314s6819.698%
DeepSeek R1 8BQ8346.5653s2,4419.698%
DeepSeek R1 8BQ8444.97100s4,4509.698%


Look what happened!
The overall speed is consistent in mid-40 tokens/sec, the VRAM usage hovers just below 10 GB, I also watched the GPU utilization and wattage and they both were consistent. What is VERY ODD here is the time of reply vs tokens written vs the actual length of output!
The model was progressively taking longer to reply, the token count was rapidly exploding, yet the replies were getting shorter. Odd, right? The quality of the replies was also slightly going downhill. The first run was the best, the cleanest and most understandable. Open WebUI collapses the reasoning block by default — click ‘Thought for X seconds’ to expand it. And I strongly suggest you do. That’s where all those tokens went. I’m sure of it. I have no other explanation why the same prompt would generate a shorter reply with 7 times as many tokens generated. And that reasoning transcript? Ugh! 4,400 tokens sounds just about right, judging by how many pages I had to scroll down to get to the end of it.
Overall, this model is solid, the code was good, skipping even numbers, doing square root optimization and was written with beginner-friendly explanation.

The conclusion – TL;DR


DeepSeek R1 8B Q8 fits more than comfortably onto a 16 GB card and would easily fit onto a 12 gig too (taking less than 10 GB VRAM) and runs at respectable 45 tokens/sec. Yes that is much slower than other 8B models, but that is not where this model’s strength is — it is in its reasoning. If you are having longer and more complex conversations, the model carries the context and gradually takes longer and longer to reply, generating more tokens, yet what you see in the end is not indicative of that. You need to see the reply itself + the reasoning behind it, so be sure you have the <think>...</think> content unhidden. That’s where the money is buried.
I think that knowing how this model came with the reply will be equally important as the answer itself. If you don’t read that reasoning behind-the-scenes part, you are leaving money on the table, because that’s where most of the tokens go (as was my case).

Now, this strength also makes it its biggest weakness – the more you converse, the slower the replies come, it will overthink, spiral out of control and burn through your work time. I think this iteration of DeepSeek is an excellent model, but this is the one where I’d start a new conversation very often to clear the context window and keep the model laser-focused that way.

If you do not believe me, read on below. Look at the first section of the reply (that is the hidden thinking process). Now compare the “sane” thinking of the RUN #1 and the “Crime and Punishment” novel this model thought up in RUN #4 below. I asked it to explain to a beginner how prime numbers are calculated and it went off the deep end, nearly drowning itself, having an existential crisis over negative numbers, and contemplating whether passing of floats to a prime is of a concern or not (What? LOL) and debating for over a minute whether 3 is a prime number or not. It would give Dostoyevsky run for his money, I swear. This model seems like a bit of a masochist. Making things too complicated for itself where it doesn’t need to – THE CRIME. While silently abusing your GPU – THE PUNISHMENT.

I don’t know. I’m torn. It’s accurate, average speed, but very capable. For the right use case, this may be a perfect model for you. If you are someone who loves diving down rabbit holes. Here is your faithful companion. Just bring with you a first-aid kit.
It’s gonna hurt.

The output (pasted and unedited) RUN #1


Thought for 3 seconds >
We are going to write a function that checks if a number is prime. > Steps: > 1. If the number is less than 2, it’s not prime. > 2. Check for divisibility from 2 up to the square root of the number (inclusive). If any divisor is found, it’s not prime. > 3. If no divisors are found, then the number is prime. > > However, note that 2 is prime, and numbers less than 2 (like 0, 1) are not. > > We’ll write a function called `is_prime` that takes an integer and returns a boolean. > > Example: > is_prime(1) -> False > is_prime(2) -> True > is_prime(10) -> False > is_prime(11) -> True > > Let’s code accordingly.

Here’s a simple Python function to check if a number is prime, along with a beginner-friendly explanation:

def is_prime(n):
if n <= 1:
return False
elif n == 2:
return True
elif n % 2 == 0:
return False
else:
for i in range(3, int(n**0.5) + 1, 2):
if n % i == 0:
return False
return True

How it works (plain English):

  1. Check for obvious non-primes:
    • If the number is less than or equal to 1, it’s not prime.
    • If the number is 2, it is prime (the smallest prime number).
    • If the number is even (other than 2), it’s not prime.
  2. Check divisibility by odd numbers:
    • For numbers greater than 2, we only need to check if they’re divisible by odd numbers (since even numbers are already handled).
    • We check from 3 up to the square root of the number (rounded up). This is efficient because a number’s smallest factor is always less than or equal to its square root.
  3. Return True if no divisors found:
    • If the number passes all these checks, it must be prime!

Example walkthrough (checking 15):

Try it yourself:

print(is_prime(11)) # Output: True
print(is_prime(15)) # Output: False
print(is_prime(1)) # Output: False
print(is_prime(9)) # Output: False
The output (pasted and unedited) RUN #4


Thought for 92 seconds >
We are going to write a function that checks if a number is prime. > Steps: > 1. If the number is less than 2, it’s not prime. > 2. If the number is 2, it is prime. > 3. If the number is even (and not 2), then it’s not prime. > 4. For odd numbers greater than 2, we check divisibility by all odd numbers starting from 3 up to the square root of the number. > > However, note that the user might input negative numbers or non-integers. We should handle that. > > Let’s define the function to work for integers only. We can convert input to integer or check for integer first. > > But the problem says “a number”, so let’s assume integer. > > We’ll do: > > def is_prime(n): > if n < 2: > return False > if n == 2: > return True > if n % 2 == 0: > return False > # Now check odd factors up to the square root > i = 3 > while i * i <= n: > if n % i == 0: > return False > i += 2 > return True > > But note: what if n is a negative number? Prime numbers are defined for positive integers only. > > So, we can consider negative numbers as not prime. > > Alternatively, we can check if n is an integer and positive. > > Let’s adjust: if n is not an integer or negative, then return False. > > However, the problem says “a number”, but in the context of prime, it must be a positive integer. > > We can do: > > if not isinstance(n, int) or n < 2: > return False > > But note: the problem doesn’t specify, so let’s stick to positive integers. > > Alternatively, we can accept only positive integers. > > But the user might pass a float? We can round? Or convert to int? But that might be error-prone. > > Since the problem says “a number”, and prime numbers are integers, we can check if n is an integer. > > Let’s do: > > if not isinstance(n, int) or n < 2: > return False > > But wait, what if n is a float representing an integer? Like 5.0? We can convert to int if it’s a whole number. > > Alternatively, we can do: > > if n < 2 or n != int(n): > return False > > But that would exclude 2.0, which is okay because 2.0 is not an integer? Actually, 2.0 is an integer value but represented as float. > > However, the problem is about prime numbers, which are defined for integers. So we can check: > > if n < 2 or not isinstance(n, int) or n % 1 != 0: > return False > > But the problem says “a number”, so maybe we should accept floats that represent integers? But then 2.0 should be prime. > > Alternatively, we can convert n to int if it’s a whole number? But then 2.0 becomes 2, which is prime. > > But let’s keep it simple: the function expects an integer. We can convert the input to an integer if it’s a whole number, but that might be confusing. > > Since the problem is for teaching a beginner, let’s assume the input is an integer. > > We’ll write the function for integer input. > > However, to be safe, we can do: > > if n < 2 or n != int(n): > return False > > But wait, for negative numbers, we already return False because n < 2. Also, for non-integers, we return False. > > But note: what if n is a string? We are not handling that. We’ll assume the input is a number. > > Alternatively, we can use: > > if type(n) is not int or n < 2: > return False > > But that might be too strict if the user passes a long integer? But in Python, int and long are the same. > > Let’s stick to the integer type. > > However, the problem does not specify, so let’s write the function for integer and if the input is not integer, we return False. > > But wait, the problem says “a number”, so maybe we should handle floats? We can convert to int if it’s a float representing an integer. > > But that might be beyond the scope. > > Since the user is a beginner, let’s keep it simple and only handle integers. > > We’ll do: > > if not isinstance(n, int) or n < 2: > return False > > But note: the condition `not isinstance(n, int)` will catch floats and other types. > > Alternatively, we can do: > > if n < 2 or n != int(n): > return False > > But that would allow negative numbers? No, because if n is negative, then n != int(n) is False (for example, -2 == int(-2.0)) but wait, let’s test: > > n = -2.0 -> n != int(n) -> -2.0 != -2 -> True, so it returns False because n < 2 is True. > > n = 2.5 -> 2.5 != 2 -> True, so returns False. > > n = 3.0 -> 3.0 == 3 -> False, so condition fails and we proceed. > > But then we have to convert 3.0 to 3? Or we can keep it as 3.0? The modulus operation with float might be slow and we are checking integers. > > Alternatively, we can convert n to int if it’s a whole number? But then we lose the negative? We already check n < 2. > > Let’s do: > > if n < 2 or n % 1 != 0: > return False > > But note: for negative numbers, %1 behavior: in Python, -1 % 1 is 0, so negative numbers would be considered whole numbers? But we want negative numbers to be non-prime. > > We can do: > > if n < 2 or n % 1 != 0: > return False > > But then for n=-2, -2 % 1 is 0, so it would pass the condition and then we check for 2? But -2 is less than 2, so it would be caught by the first condition. > > Actually, the condition is: if n < 2 OR n % 1 != 0. > > So for n=-2: n < 2 is True, so return False. > > For n=2.5: 2.5 % 1 = 0.5 -> True, so return False. > > For n=3.0: 3.0 % 1 = 0 -> condition fails, so we proceed. > > Then we have to check if 3.0 is prime. But our function uses modulus with integers (3 % 3, etc). But 3.0 % 3 is 0.0, which is okay. > > However, we are doing modulus with integers (3,5,…). We can convert n to int? But then we lose the negative? But we already check n<2. > > Alternatively, we can convert n to an integer if it’s a whole number? But then we are effectively truncating. > > Since the problem is about prime numbers, and prime numbers are defined for positive integers, we can convert n to an integer if it’s a whole number and positive. > > But let’s keep it simple and only accept integers. The problem says “a number”, but in the context, it’s a prime number. > > We’ll do: > > if not isinstance(n, int) or n < 2: > return False > > This way, if n is a float, it returns False. > > But the user might pass a float. We can also allow floats that are whole numbers? But then we have to convert. > > Let me decide: the function is for integers. We’ll return False for non-integers and negative numbers. > > So: > > if not isinstance(n, int) or n < 2: > return False > > Then the rest. > > However, the problem does not specify, so let’s stick to integers. > > But note: the original code did not handle non-integers. We are adding a condition. > > Alternatively, we can leave it without type checking and assume the input is integer. > > Since the problem is for teaching, let’s assume the input is an integer. > > We’ll write the function without type checking and with the condition n>=2. > > But then if the user passes a float, it might not work as expected. > > Let me see: if n is a float and >=2, then we do modulus with integers? That might not be the same. > > Example: n=4.0, then 4.0 % 2 == 0.0 -> True, so we return False. But that’s correct. > > But what about n=4.5? 4.5 % 2 = 0.5 -> not 0, so we continue. Then we check odd factors. But 4.5 is not an integer, so it shouldn’t be prime. > > However, our function does not check for integer. We are just doing modulus. The modulus operation for non-integers might be defined, but the concept of prime is for integers. > > We can change the condition to: > > if n < 2 or not isinstance(n, int): > return False > > But then if the user passes a float, it returns False. > > Alternatively, we can convert the input to int if it’s a whole number, but then we have to check if it’s whole. > > Let me propose a version that accepts integers and floats that represent integers. > > We can do: > > if n < 2 or n % 1 != 0: > return False > > Then, we can convert n to int? Or keep it as float? But then in the loop, we are using integers (i) and modulus with n (which is float). > > But modulus between float and int is defined, but we are comparing with 0.0? > > Example: 4.0 % 2 == 0.0 -> True. > > But then we are doing: > > i = 3 > while i * i <= n: # 3*3=9 <= 4.0? False, so it returns True for 4.0? That’s not correct. > > Wait, for n=4.0, we first check n<2 -> False, then n%1==0 -> True, so we proceed. Then we check evenness? But we removed the evenness check. > > Let me restructure: we want to handle both even and odd, but if we remove the evenness check, we have to check for evenness separately. > > Alternatively, we can do: > > if n < 2 or n % 1 != 0: > return False > > # Now n is a positive integer (or a float that is a whole number, but we can convert to int to be safe) > > # But wait, we are using modulus with integers, so if n is float, then n % i (where i is integer) is float. > > # We can convert n to int at the beginning? > > Let’s convert n to int if it’s a whole number? But we already checked n % 1 == 0, so it’s whole. > > We can do: > > n = int(n) > > But wait, if n is negative, we already return False. So n is positive. > > So: > > if n < 2 or n % 1 != 0: > return False > > n = int(n) > > Then we proceed. > > But then we are converting the input to an integer. But the input might be a float. We are allowed to do that. > > Alternatively, we can keep it as float and adjust the modulus? But then the evenness check: we can check n % 2 == 0.0. > > But let’s keep it simple and convert to int. > > Steps: > > if n < 2 or n % 1 != 0: > return False > > n = int(n) > > Then the rest. > > But then we are doing two checks: n % 1 and then converting. We can do: > > if n < 2 or n != int(n): > return False > > n = int(n) > > But then we are converting twice? No, we can do: > > if n < 2 or n != int(n): > return False > > # Now n is int(n), so we can use n as integer. > > But note: n might be a float, but if n != int(n), we return False. Then if we pass, we are using n as integer? But n is still the same type. > > Example: n=3.0 -> 3.0 != 3 -> True, so return False? That’s not what we want. > > Wait, 3.0 != 3 is True? In Python, 3.0 and 3 are different types, so they are not equal. But we want to consider 3.0 as 3. > > We can do: > > if n < 2 or n % 1 != 0 or n != int(n): > return False > > But that’s redundant. > > Alternatively, we can do: > > if n < 2 or not isinstance(n, int): > return False > > Then we don’t have to worry about floats. > > I think for simplicity and clarity, we’ll assume the input is an integer. > > So the function: > > def is_prime(n): > if n < 2: > return False > # Check if n is even > if n % 2 == 0 and n != 2: > return False > # Then check odd factors > # But wait, we already handled even numbers. > > But the original code did: > > if n < 2 or n != int(n): > return False > > No, we decided to not use that. > > Let’s go back to the original code without type checking, but then we have to handle even and odd. > > We’ll do: > > def is_prime(n): > if n < 2: > return False > # Check even numbers > if n % 2 == 0: > return n == 2 > # Then check odd factors > # But wait, we already handled even numbers, so for n==2, we return True, for even numbers greater than 2, False. > > But then we have to write the odd factors check. > > Alternatively, we can do: > > if n < 2: > return False > if n == 2: > return True > if n % 2 == 0: > return False > > But that’s redundant. > > We’ll stick to the initial code structure. > > Since the problem is for teaching, let’s keep the function simple and only handle integers. > > We’ll do: > > def is_prime(n): > if n < 2: > return False > # We’ll assume n is an integer from this point > # Check even numbers > if n % 2 == 0: > return n == 2 > # Then check odd factors > # … > > But then we have to handle odd numbers. > > Alternatively, we can do: > > if n < 2 or n != int(n): > return False > > # Now n is an integer > > But as discussed, 3.0 != 3 is True, so we return False for 3.0. > > We want to allow 3.0. > > So we can do: > > if n < 2 or not isinstance(n, int): > return False > > Then we don’t care about floats. > > I think the best is to assume integer input. > > Let’s write the function for integers. > > Code: > > def is_prime(n): > if n < 2: > return False > if n == 2: > return True > if n % 2 == 0: > return False > # Now n is odd and >=3 > # Check odd factors from 3 to sqrt(n) > i = 3 > while i * i <= n: > if n % i == 0: > return False > i += 2 > return True > > But wait, what about n=9? 9 is odd, but 9 % 3 ==0, so returns False, correct. > > But what about n=15? 15 % 3 ==0, returns False. > > What about n=25? 25 % 5 ==0, but 5 is not in the loop because we only check odd factors starting from 3, and 5 is odd, but we start at 3 and then 5,7,9,… but 9*9=81>25, so we don’t reach 5? > > Let me check: for n=25, i starts at 3, 3*3=9<=25 -> 25%3 !=0, then i=5, 5*5=25<=25 -> 25%5==0 -> returns False. Correct. > > But in the loop, we are incrementing i by 2, so we skip even numbers, which is good because we already handled even numbers. > > However, what if n is even and greater than 2? We return False. Correct. > > What if n is 2? We return True. Correct. > > What if n is 3? > n<2 -> False > n==2 -> False > n%2==0 -> 3%2=1 -> False > then i=3, 3*3=9<=3? False, so returns True. Correct. > > What if n=4? > n<2 -> False > n==2 -> False > n%2==0 -> True, and n!=2, so returns False. Correct. > > What if n=9? > n<2 -> False > n==2 -> False > n%2==0 -> 9%2=1 -> False > i=3, 3*3=9<=9 -> 9%3==0 -> returns False. Correct. > > What if n=25? > i=3: 3*3=9<=25 -> 25%3 !=0 -> i=5 > i=5: 5*5=25<=25 -> 25%5==0 -> False. Correct. > > What if n=49? > i=3: 3*3=9<=49 -> 49%3!=0 > i=5: 5*5=25<=49 -> 49%5!=0 > i=7: 7*7=49<=49 -> 49%7==0 -> False. Correct. > > What if n=1? -> False. Correct. > > What if n=0? -> False. Correct. > > What if n=-1? -> False. Correct. > > But what if n is a string? We are not checking type, so it will throw an error. > > But the problem is for teaching, so we assume integer input. > > We’ll write the function as above. > > However, the original user context might be in a system that passes integers. > >

Let me write the final function. To determine if a number is prime, follow these steps:

  1. Check if the number is less than 2: Numbers less than 2 are not prime.
  2. Check if the number is 2: 2 is the only even prime number.
  3. Check if the number is even: If the number is even and not 2, it is not prime.
  4. Check for odd factors: For odd numbers, test divisibility by odd integers starting from 3 up to the square root of the number. If any divisor is found, the number is not prime.

Here’s the Python code implementing this logic:

def is_prime(n):
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
i = 3
while i * i <= n:
if n % i == 0:
return False
i += 2
return True

Explanation:

This approach ensures efficient and accurate prime number identification.

Need Help?

Need help streamlining your processes or solving tricky business problems? I offer one-on-one consultations to get you unstuck fast. Book a free consultation with me today at goarcherdynamics.com.

Want more practical tips and workflow hacks? I publish them regularly on my blog — check it out and subscribe for newsletter updates: goarcherdynamics.com

Jiri Krecek Avatar

Posted by

Leave a Reply

Discover more from Archer Dynamics

Subscribe now to keep reading and get access to the full archive.

Continue reading