🇬🇧 English
The short answer first. The AI HAT+ 2 cannot mine Monero, and its 8 GB is not your Pi's memory.
The Pi's own processor can, and this page works out exactly what that is worth, with today's numbers.
It comes to about a baht a day, both ways. The interesting part is why the accelerator is no help at all.
🇹🇭 ไทย
ตอบสั้น ๆ ก่อน AI HAT+ 2 ขุด Monero ไม่ได้ และ 8 GB ของมันก็ไม่ใช่หน่วยความจำของ Pi คุณ
ตัวประมวลผลของ Pi เองขุดได้ และหน้านี้จะคำนวณให้ดูว่ามันคุ้มแค่ไหน ด้วยตัวเลขของวันนี้
ผลออกมาราวบาทเดียวต่อวัน ทั้งสองทาง ส่วนที่น่าสนใจคือทำไมตัวเร่งความเร็วถึงช่วยอะไรไม่ได้เลย
🇨🇳 中文
先说短的答案。AI HAT+ 2 挖不了 Monero,它那 8 GB 也不是你 Pi 的内存。
Pi 自己的处理器可以挖,这一页会用今天的数字算清楚它到底值多少。
结果大约是一天一泰铢,两边都是。有意思的是,为什么那个加速器一点忙都帮不上。
| What it isมันคืออะไร它是什么 | Can it mine Monero?ขุด Monero ได้ไหม能挖 Monero 吗 | |
|---|---|---|
| Pi 5 processorตัวประมวลผลของ Pi 5Pi 5 的处理器 | what: four Cortex-A76 cores, general purposeคืออะไร: สี่คอร์ Cortex-A76 แบบใช้งานทั่วไป是什么:四个 Cortex-A76 核心,通用 | mines: yes, this is the only part that doesขุดได้: ได้ มีแค่ส่วนนี้ที่ทำได้能挖吗:能,而且只有它能 |
| Pi 5 memory, 8 GBหน่วยความจำ Pi 5 ขนาด 8 GBPi 5 的 8 GB 内存 | what: ordinary system RAMคืออะไร: แรมของระบบตามปกติ是什么:普通的系统内存 | mines: it holds the 2 GB table, so yes it helpsขุดได้: ใช้เก็บตาราง 2 GB ได้ จึงช่วยได้จริง能挖吗:能放下那张 2 GB 的表,所以有用 |
| AI HAT+ 2, Hailo-10HAI HAT+ 2 ชิป Hailo-10HAI HAT+ 2,Hailo-10H | what: a fixed-function neural acceleratorคืออะไร: ตัวเร่งความเร็วโครงข่ายประสาทแบบตายตัว是什么:一个固定功能的神经加速器 | mines: no, it cannot run arbitrary codeขุดได้: ไม่ได้ มันรันโค้ดทั่วไปไม่ได้能挖吗:不能,它跑不了任意代码 |
| The HAT's 8 GB8 GB ของ HATHAT 上的 8 GB | what: the accelerator's own, over PCIeคืออะไร: เป็นของตัวเร่งความเร็วเอง ผ่าน PCIe是什么:加速器自己的,走 PCIe | mines: no, the processor cannot use itขุดได้: ไม่ได้ ตัวประมวลผลใช้มันไม่ได้能挖吗:不能,处理器用不了它 |
🧩 Tutorial 1 — What can mine, and what cannot · บทที่ 1 — อะไรขุดได้ และอะไรขุดไม่ได้ · 教程 1 —— 什么能挖,什么不能
🇬🇧 English
Monero uses an algorithm called RandomX. It was designed, on purpose, to be bad on everything except an ordinary processor.
Knowing what it wants tells you immediately why the HAT is not invited.
🇹🇭 ไทย
Monero ใช้อัลกอริทึมชื่อ RandomX ซึ่งถูกออกแบบมาโดยตั้งใจให้ทำงานได้แย่กับทุกอย่าง ยกเว้นตัวประมวลผลธรรมดา
พอรู้ว่ามันต้องการอะไร ก็จะเข้าใจทันทีว่าทำไม HAT ถึงไม่ได้ถูกเชิญ
🇨🇳 中文
Monero 用的算法叫 RandomX。它是故意被设计成:除了普通处理器之外,在别的东西上都跑不好。
知道它要什么,你立刻就明白为什么 HAT 没被邀请。
1 What RandomX asks for · RandomX ต้องการอะไร · RandomX 要的是什么
🇬🇧 English
Four things, and your machine either has them or it does not. This script reads all four.
Run it on the Pi. It runs here too, which is how the output below exists.
🇹🇭 ไทย
สี่อย่าง และเครื่องของคุณมีหรือไม่มีก็ว่ากันไป สคริปต์นี้อ่านทั้งสี่อย่างให้
รันบน Pi ได้ และรันที่นี่ก็ได้ ซึ่งเป็นที่มาของผลลัพธ์ข้างล่าง
🇨🇳 中文
四样东西,你的机器要么有要么没有。这个脚本四样都读。
在 Pi 上跑得了,在这儿也跑得了,下面的输出就是这么来的。
📄 NEW FILE · whatis1.py
"""whatis1.py — what does this machine actually offer a RandomX miner?
RandomX is the algorithm Monero uses. It was designed on purpose to run
well on an ordinary processor and badly on anything else. This reads the
four things it cares about, on whatever you run it on.
"""
import os
import platform
import sys
from pathlib import Path
# RandomX keeps a 2 GB table in memory and reads it at random. With room
# for it, the miner runs fast mode. Without, it falls back to light mode,
# which is many times slower.
DATASET_GB = 2.08
sys.stdout.reconfigure(encoding="utf-8")
def cpu_flags():
"""The processor's feature list, where the system will tell us."""
cpuinfo = Path("/proc/cpuinfo")
if cpuinfo.exists():
text = cpuinfo.read_text(encoding="utf-8", errors="replace")
for line in text.splitlines():
if line.lower().startswith(("flags", "features")):
return set(line.split(":", 1)[1].split())
return set()
def total_ram_gb():
"""How much memory the processor can actually use."""
pages = getattr(os, "sysconf_names", {}).get("SC_PHYS_PAGES")
if pages:
return os.sysconf("SC_PHYS_PAGES") * os.sysconf("SC_PAGE_SIZE") / 1e9
# Windows has no sysconf. Ask the kernel directly.
import ctypes
class Status(ctypes.Structure):
_fields_ = [("dwLength", ctypes.c_ulong),
("dwMemoryLoad", ctypes.c_ulong),
("ullTotalPhys", ctypes.c_ulonglong),
("ullAvailPhys", ctypes.c_ulonglong),
("ullTotalPageFile", ctypes.c_ulonglong),
("ullAvailPageFile", ctypes.c_ulonglong),
("ullTotalVirtual", ctypes.c_ulonglong),
("ullAvailVirtual", ctypes.c_ulonglong),
("ullAvailExtendedVirtual", ctypes.c_ulonglong)]
status = Status()
status.dwLength = ctypes.sizeof(Status)
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(status))
return status.ullTotalPhys / 1e9
def main():
flags = cpu_flags()
ram = total_ram_gb()
cores = os.cpu_count() or 0
print("machine ", platform.machine(), "-", platform.system())
print("cores ", cores)
print(f"memory {ram:.1f} GB")
# Hardware AES is the single biggest difference. Without it RandomX
# does the same work in software, several times slower.
aes = bool(flags & {"aes", "aes_ni", "pmull", "sha2"})
print("hardware AES ", "yes" if aes else ("no" if flags else "cannot tell here"))
print()
if ram >= DATASET_GB + 1:
print(f"fast mode yes, {DATASET_GB} GB table fits with room to spare")
else:
print(f"fast mode no, needs about {DATASET_GB} GB free just for the table")
# Huge pages let the processor find that table with fewer lookups.
# On Linux this is a number you can change; it is worth a third more.
huge = Path("/proc/sys/vm/nr_hugepages")
if huge.exists():
print("huge pages ", huge.read_text().strip(), "(want 1280 or more)")
else:
print("huge pages not a setting on this system")
print()
print("What none of this asks about: any accelerator you have plugged in.")
print("RandomX runs on the processor. There is nowhere else for it to go.")
if __name__ == "__main__":
main()
🖥️ ON AN ARM64 MACHINE · the same architecture family as a Pi 5
machine aarch64 - Linux
cores 20
memory 130.7 GB
hardware AES yes
fast mode yes, 2.08 GB table fits with room to spare
huge pages 0 (want 1280 or more)
What none of this asks about: any accelerator you have plugged in.
RandomX runs on the processor. There is nowhere else for it to go.
| Line | What it does · ทำอะไร · 做什么 |
|---|---|
| DATASET_GB = 2.08 | RandomX reads a 2 GB table at random. It has to be in memory.RandomX อ่านตารางขนาด 2 GB แบบสุ่ม มันต้องอยู่ในหน่วยความจำRandomX 会随机读一张 2 GB 的表。它必须在内存里。 |
| aes = bool(flags & {"aes", "aes_ni", "pmull", "sha2"}) | Hardware AES is the biggest single difference to the speed.AES แบบฮาร์ดแวร์คือสิ่งที่ทำให้ความเร็วต่างกันมากที่สุด硬件 AES 是对速度影响最大的一项。 |
| huge = Path("/proc/sys/vm/nr_hugepages") | Huge pages cut the lookups to find that table. Worth a third more.huge pages ลดจำนวนครั้งที่ต้องค้นหาตารางนั้น เพิ่มความเร็วได้ราวหนึ่งในสามhuge pages 能减少查那张表的次数。大约能多三分之一。 |
| RandomX needsRandomX ต้องการRandomX 需要 | A Pi 5 processorตัวประมวลผล Pi 5Pi 5 的处理器 | A Hailo-10Hชิป Hailo-10HHailo-10H |
|---|---|---|
| to run code chosen at randomรันโค้ดที่ถูกสุ่มเลือก运行随机选出的代码 | Pi: that is what a processor isPi: นั่นคือหน้าที่ของตัวประมวลผลPi:处理器就是干这个的 | Hailo: no, it runs compiled graphsHailo: ไม่ได้ มันรันกราฟที่คอมไพล์มาแล้วHailo:不行,它跑的是编译好的图 |
| 2 GB of random readsการอ่านแบบสุ่ม 2 GB2 GB 的随机读 | Pi: yes, from the 8 GBPi: ได้ จาก 8 GB ที่มีPi:可以,从那 8 GB 里 | Hailo: its memory is for weightsHailo: หน่วยความจำของมันมีไว้เก็บน้ำหนักโมเดลHailo:它的内存是放权重的 |
| floating point and AESเลขทศนิยมและ AES浮点和 AES | Pi: both, in hardwarePi: มีทั้งคู่ ในระดับฮาร์ดแวร์Pi:都有,硬件级 | Hailo: INT4 and INT8 onlyHailo: มีแค่ INT4 กับ INT8Hailo:只有 INT4 和 INT8 |
- Run it on the Pi. Check fast mode says yes.
- If huge pages says 0, that is a third of your speed missing.
sudo sysctl -w vm.nr_hugepages=1280, then run it again.- Notice nothing in the output mentions the HAT. There is nothing to say.
- รันบน Pi แล้วเช็กว่า fast mode ขึ้นว่า yes
- ถ้า huge pages ขึ้น 0 แปลว่าคุณเสียความเร็วไปราวหนึ่งในสาม
sudo sysctl -w vm.nr_hugepages=1280แล้วรันใหม่- สังเกตว่าไม่มีอะไรในผลลัพธ์พูดถึง HAT เลย เพราะไม่มีอะไรจะพูด
- 在 Pi 上跑。确认 fast mode 是 yes。
- 如果 huge pages 是 0,你少了大约三分之一的速度。
sudo sysctl -w vm.nr_hugepages=1280,再跑一次。- 注意输出里没有一句提到 HAT。因为没什么可说的。
💷 Tutorial 2 — The arithmetic · บทที่ 2 — การคำนวณ · 教程 2 —— 算一笔账
🇬🇧 English
Two numbers decide everything: what a hashrate earns, and what the power costs. Both are small.
Fetched live, so this is today's answer and not a forum post from four years ago.
🇹🇭 ไทย
มีสองตัวเลขที่ตัดสินทุกอย่าง คือแฮชเรตหาเงินได้เท่าไหร่ กับค่าไฟเท่าไหร่ ทั้งคู่เล็กมาก
ดึงสดมา นี่จึงเป็นคำตอบของวันนี้ ไม่ใช่โพสต์ในเว็บบอร์ดเมื่อสี่ปีก่อน
🇨🇳 中文
两个数字决定一切:算力赚多少,电费花多少。两个都很小。
实时取的,所以这是今天的答案,不是四年前论坛上的帖子。
2 What it earns, against what it costs · หาได้เท่าไหร่ เทียบกับจ่ายเท่าไหร่ · 赚多少,对上花多少
🇬🇧 English
Your share of the reward is your share of the work. That is the whole of mining economics in one sentence.
The default hashrate here is a guess. Replace it with yours and the answer becomes about your machine.
🇹🇭 ไทย
ส่วนแบ่งรางวัลของคุณคือส่วนแบ่งงานของคุณ นั่นคือเศรษฐศาสตร์ของการขุดทั้งหมดในประโยคเดียว
ค่าแฮชเรตเริ่มต้นตรงนี้เป็นการเดา เปลี่ยนเป็นของคุณแล้วคำตอบจะกลายเป็นเรื่องของเครื่องคุณ
🇨🇳 中文
你能分到的奖励,就是你出的力占多少。挖矿的经济学一句话说完了。
这里默认的算力是猜的。换成你自己的,答案才是关于你机器的。
📄 NEW FILE · money1.py
"""money1.py — what a given hashrate earns, against what the power costs.
Every number that moves is fetched now. Put your own measured hashrate in
and the answer is about your machine, not about a forum post from 2021.
"""
import json
import sys
import urllib.request
NETWORK = "https://localmonero.co/blocks/api/get_stats"
PRICE = "https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=usd,thb"
# Measure yours with: xmrig --bench=1M
HASHRATE = float(sys.argv[1]) if len(sys.argv) > 1 else 500.0
# A Pi 5 working all four cores. Measure yours with a plug meter; this is
# the number most worth replacing with your own.
WATTS = float(sys.argv[2]) if len(sys.argv) > 2 else 9.0
# Thai household electricity, baht per kilowatt hour.
BAHT_PER_KWH = float(sys.argv[3]) if len(sys.argv) > 3 else 4.5
# Monero aims at one block every two minutes.
BLOCKS_A_DAY = 720
ATOMIC = 1e12
sys.stdout.reconfigure(encoding="utf-8")
def get(url):
request = urllib.request.Request(url, headers={"User-Agent": "a lesson"})
with urllib.request.urlopen(request, timeout=30) as response:
return json.load(response)
def main():
chain = get(NETWORK)
price = get(PRICE)["monero"]
network = chain["hashrate"]
reward = chain["last_reward"] / ATOMIC
print(f"network hashrate {network / 1e9:10.2f} GH/s")
print(f"block reward {reward:10.4f} XMR")
print(f"XMR price {price['usd']:10.2f} USD "
f"{price['thb']:,.0f} THB")
print(f"your hashrate {HASHRATE:10.0f} H/s")
print()
# Mining is a lottery with tickets in proportion to work done. Over a
# long enough time your share of the reward is your share of the work.
share = HASHRATE / network
xmr_a_day = BLOCKS_A_DAY * reward * share
baht_a_day = xmr_a_day * price["thb"]
power_kwh = WATTS * 24 / 1000
power_baht = power_kwh * BAHT_PER_KWH
print(f"your share of the network 1 in {1 / share:,.0f}")
print(f"earns per day {xmr_a_day:.8f} XMR "
f"{baht_a_day:6.2f} baht")
print(f"electricity per day {power_kwh:.3f} kWh "
f"{power_baht:6.2f} baht ({WATTS:.0f} W)")
print()
net = baht_a_day - power_baht
word = "makes" if net >= 0 else "loses"
print(f"so it {word} {abs(net):.2f} baht a day, "
f"{abs(net) * 365:.0f} baht a year")
if net < 0:
# The honest way to put it: how much cheaper would power have to be?
needed = baht_a_day / power_kwh if power_kwh else 0
print(f"to break even, electricity would have to cost "
f"{needed:.2f} baht per kWh")
print(f"you are paying {BAHT_PER_KWH:.2f}")
if __name__ == "__main__":
main()
🖥️ WHAT IT PRINTED · live, at 500 H/s and 4.50 baht a unit
network hashrate 6.04 GH/s
block reward 0.6007 XMR
XMR price 556.06 USD 18,610 THB
your hashrate 500 H/s
your share of the network 1 in 12,085,486
earns per day 0.00003579 XMR 0.67 baht
electricity per day 0.216 kWh 0.97 baht (9 W)
so it loses 0.31 baht a day, 112 baht a year
to break even, electricity would have to cost 3.08 baht per kWh
you are paying 4.50
🇬🇧 English
Run it again at 750 H/s, the optimistic end, and it makes 0.03 baht a day. Ten baht a year.
So the running cost is a coin flip. Whether it wins or loses depends on numbers you have not measured yet.
🇹🇭 ไทย
ลองรันใหม่ที่ 750 H/s ซึ่งเป็นปลายทางที่ดีที่สุด มันจะได้ 0.03 บาทต่อวัน หรือสิบบาทต่อปี
ค่าใช้จ่ายในการเดินเครื่องจึงเป็นเหมือนการโยนหัวก้อย จะได้หรือเสียขึ้นอยู่กับตัวเลขที่คุณยังไม่ได้วัด
🇨🇳 中文
换成乐观的 750 H/s 再跑一次,它一天赚 0.03 泰铢。一年十泰铢。
所以运行成本基本是掷硬币。赢还是输,取决于你还没量过的那些数字。
- Run it. Then run it with your own measured hashrate.
- Put your real electricity rate in. Check a bill, do not guess.
- Measure the watts with a plug meter if you have one.
- Whichever way it lands, you now know by how much.
- รันดู แล้วรันอีกครั้งด้วยค่าแฮชเรตที่คุณวัดเอง
- ใส่ค่าไฟจริงของคุณ ดูจากบิล อย่าเดา
- วัดกำลังไฟด้วยมิเตอร์เสียบปลั๊ก ถ้ามี
- ไม่ว่าผลจะออกทางไหน ตอนนี้คุณรู้แล้วว่าต่างกันเท่าไหร่
- 运行。然后用你自己量到的算力再跑一次。
- 填你真实的电价。去看账单,别猜。
- 有功率计的话,量一下瓦数。
- 不管结果落在哪边,你现在知道差多少了。
3 Actually running it · ลงมือรันจริง · 真的把它跑起来
🇬🇧 English
If you want to do it anyway, and there are good reasons to, this is the setup.
Mine into a pool. Step 4 shows what solo mining on a Pi actually means.
🇹🇭 ไทย
ถ้ายังอยากทำอยู่ดี ซึ่งก็มีเหตุผลดี ๆ อยู่ นี่คือวิธีตั้งค่า
ให้ขุดเข้าพูล ส่วนขั้นที่ 4 จะแสดงว่าการขุดเดี่ยวบน Pi หมายความว่าอะไรจริง ๆ
🇨🇳 中文
如果你还是想做——这有不少正当理由——设置是这样的。
挖进矿池。第 4 步会告诉你在 Pi 上单独挖矿到底意味着什么。
💻 ON THE PI · build the miner, then measure before you commit
sudo apt install -y git build-essential cmake libuv1-dev libssl-dev libhwloc-dev
git clone https://github.com/xmrig/xmrig && cd xmrig
mkdir build && cd build && cmake .. && make -j4
# Huge pages first. Without them you lose about a third.
sudo sysctl -w vm.nr_hugepages=1280
# The number this whole page is waiting for:
./xmrig --bench=1M
📄 NEW FILE · pool.json
{
"autosave": true,
"cpu": {
"enabled": true,
"huge-pages": true,
"max-threads-hint": 75,
"priority": 1
},
"opencl": false,
"cuda": false,
"randomx": {
"mode": "fast",
"1gb-pages": false
},
"pools": [
{
"url": "pool.supportxmr.com:3333",
"user": "YOUR_MONERO_ADDRESS",
"pass": "pi5",
"keepalive": true,
"tls": true
}
]
}
| Line | What it does · ทำอะไร · 做什么 |
|---|---|
| "max-threads-hint": 75 | Three of the four cores. The fourth keeps the Pi answering you.ใช้สามในสี่คอร์ คอร์ที่เหลือไว้ให้ Pi ยังตอบคุณได้四个核用三个。剩下那个让 Pi 还能理你。 |
| "mode": "fast" | Uses the 2 GB table. Needs the memory, and is worth it.ใช้ตาราง 2 GB ต้องมีหน่วยความจำพอ และคุ้มค่า用那张 2 GB 的表。要有内存,而且值得。 |
| "opencl": false, | There is nothing to offload to. The HAT is not an option here.ไม่มีอะไรให้ส่งงานไปทำ HAT ไม่ใช่ตัวเลือกตรงนี้没有可以卸载过去的东西。HAT 在这儿不是一个选项。 |
| "tls": true | The pool sees your address either way. Encrypt the link anyway.ยังไงพูลก็เห็นที่อยู่ของคุณ แต่ก็ควรเข้ารหัสการเชื่อมต่ออยู่ดี反正矿池会看到你的地址。链路还是加密的好。 |
vcgencmd measure_temp for the first day.
RandomX เร่งทุกคอร์เต็มที่ตลอดเวลา ซึ่งไม่เหมือนโปรเจกต์ Pi ส่วนใหญ่ ถ้าไม่มีพัดลมระบายความร้อน มันจะลดความเร็วลง และ Pi ที่ถูกลดความเร็วจะหาได้น้อยลงโดยใช้ไฟเท่าเดิม คอยดูด้วย vcgencmd measure_temp ในวันแรก
RandomX 会让每个核心持续满载,这和大多数 Pi 项目不一样。没有主动散热它会降频,而降了频的 Pi 赚得更少、电却照吃。第一天用 vcgencmd measure_temp 盯着它。
- Build xmrig. Run
--bench=1Mand write the number down. - Put that number into
money1.py. - Only then decide whether to point it at a pool.
- If you do, watch the temperature for a day.
- บิลด์ xmrig รัน
--bench=1Mแล้วจดตัวเลขไว้ - เอาตัวเลขนั้นใส่ใน
money1.py - แล้วค่อยตัดสินใจว่าจะชี้ไปที่พูลไหม
- ถ้าทำ ให้เฝ้าดูอุณหภูมิสักวันหนึ่ง
- 编译 xmrig。跑
--bench=1M,把数字记下来。 - 把那个数字填进
money1.py。 - 然后再决定要不要接上矿池。
- 要接的话,盯一天温度。
🎯 Tutorial 3 — Three challenges · บทที่ 3 — โจทย์สามข้อ · 教程 3 —— 三道题
🇬🇧 English
All three answer a question with a number instead of an opinion. Every one was run.
🇹🇭 ไทย
ทั้งสามข้อตอบคำถามด้วยตัวเลข ไม่ใช่ความเห็น และทุกข้อถูกรันจริง
🇨🇳 中文
三道题都用数字而不是意见来回答。每一道都跑过。
4 Try first. The answers are folded away. · ลองเองก่อน เฉลยพับซ่อนไว้ · 先自己试。答案折起来放着。
🇬🇧 English
They share the live data from step 2, so your answers will differ from mine by whatever the market did.
🇹🇭 ไทย
ทั้งสามใช้ข้อมูลสดชุดเดียวกับขั้นที่ 2 คำตอบของคุณจึงต่างจากของผมตามที่ตลาดขยับไป
🇨🇳 中文
它们共用第 2 步的实时数据,所以你的答案会因为行情变动而和我的不同。
1How long until you find a block alone? · อีกนานแค่ไหนกว่าจะเจอบล็อกด้วยตัวเอง · 自己挖,多久能挖到一个块?
🇬🇧 English
A pool pays a trickle. Solo pays nothing until it pays everything.
Difficulty is how many tries the whole network expects to need. Divide it by yours.
🇹🇭 ไทย
พูลจ่ายทีละนิด ส่วนการขุดเดี่ยวไม่จ่ายอะไรเลย จนกว่าจะจ่ายทั้งก้อน
ค่าความยากคือจำนวนครั้งที่ทั้งเครือข่ายคาดว่าต้องลอง เอามาหารด้วยของคุณ
🇨🇳 中文
矿池一点一点地付。单独挖则一分不付,直到一次付清。
难度就是整个网络预计要试多少次。拿它除以你的。
Show the answerดูเฉลย看答案
📄 solo1.py
"""solo1.py — challenge 1: how long until you find a block on your own?
Mining into a pool pays you a steady trickle. Mining alone pays nothing
at all until you find a whole block, and then it pays everything. This is
the wait, and it is the number that decides which you should do.
"""
import json
import math
import sys
import urllib.request
NETWORK = "https://localmonero.co/blocks/api/get_stats"
HASHRATE = float(sys.argv[1]) if len(sys.argv) > 1 else 500.0
sys.stdout.reconfigure(encoding="utf-8")
def main():
request = urllib.request.Request(NETWORK, headers={"User-Agent": "a lesson"})
with urllib.request.urlopen(request, timeout=30) as response:
chain = json.load(response)
difficulty = chain["difficulty"]
# Difficulty is how many hashes the whole network expects to try per
# block. Divide by your own rate and you get your own expected wait.
seconds = difficulty / HASHRATE
years = seconds / (365.25 * 24 * 3600)
print(f"difficulty {difficulty:,}")
print(f"your hashrate {HASHRATE:,.0f} H/s")
print(f"expected wait {years:,.1f} years")
print()
# It is not a countdown. Every attempt is independent, so the chance
# of having found one by a given date follows this curve.
print("chance of having found a block by then:")
for months in (1, 12, 60, 120):
chance = 1 - math.exp(-(months * 30.4 * 24 * 3600) / seconds)
label = f"{months} month" + ("s" if months > 1 else "")
print(f" after {label:10} {chance * 100:7.4f}%")
print()
print("A pool splits the reward by work done, so you are paid the")
print("average instead of waiting for the whole thing.")
if __name__ == "__main__":
main()
🖥️ WHAT IT PRINTED · at 500 H/s
difficulty 725,129,170,594
your hashrate 500 H/s
expected wait 46.0 years
chance of having found a block by then:
after 1 month 0.1809%
after 12 months 2.1499%
after 60 months 10.2970%
after 120 months 19.5337%
2How long until the hardware pays for itself? · อีกนานแค่ไหนกว่าฮาร์ดแวร์จะคืนทุน · 硬件多久能回本?
🇬🇧 English
Step 2 ignored what the machine cost. Add it, and also ask the question nobody asks.
The same money, spent on the coin directly, buys how much?
🇹🇭 ไทย
ขั้นที่ 2 ไม่ได้นับค่าเครื่อง ใส่เข้าไป แล้วถามคำถามที่ไม่มีใครถามด้วย
เงินก้อนเดียวกัน ถ้าเอาไปซื้อเหรียญตรง ๆ จะได้เท่าไหร่
🇨🇳 中文
第 2 步没算机器的钱。把它加上,再问一个没人问的问题。
同样这笔钱,直接去买币,能买多少?
Show the answerดูเฉลย看答案
📄 payback1.py
"""payback1.py — challenge 2: how long until the hardware pays for itself?
The mining arithmetic in step 4 ignored what the machine cost. This does
not. It also asks the other question: what would the same money have
bought if you had simply used it to buy the coin.
"""
import json
import sys
import urllib.request
NETWORK = "https://localmonero.co/blocks/api/get_stats"
PRICE = "https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=usd,thb"
# What the parts cost, in US dollars, at list price.
PARTS = {"Raspberry Pi 5, 8GB": 80.0,
"AI HAT+ 2, 8GB": 130.0,
"power supply, case, card": 40.0}
HASHRATE = float(sys.argv[1]) if len(sys.argv) > 1 else 500.0
WATTS = float(sys.argv[2]) if len(sys.argv) > 2 else 9.0
BAHT_PER_KWH = 4.5
BLOCKS_A_DAY = 720
ATOMIC = 1e12
sys.stdout.reconfigure(encoding="utf-8")
def get(url):
request = urllib.request.Request(url, headers={"User-Agent": "a lesson"})
with urllib.request.urlopen(request, timeout=30) as response:
return json.load(response)
def main():
chain = get(NETWORK)
price = get(PRICE)["monero"]
baht_per_usd = price["thb"] / price["usd"]
spent = sum(PARTS.values())
for what, cost in PARTS.items():
print(f" {what:28} {cost:7.2f} USD")
print(f" {'total':28} {spent:7.2f} USD "
f"= {spent * baht_per_usd:,.0f} baht")
print()
share = HASHRATE / chain["hashrate"]
xmr_a_year = BLOCKS_A_DAY * 365 * (chain["last_reward"] / ATOMIC) * share
earns = xmr_a_year * price["thb"]
power = WATTS * 24 * 365 / 1000 * BAHT_PER_KWH
net = earns - power
print(f"mines per year {xmr_a_year:.6f} XMR = {earns:,.0f} baht")
print(f"power per year {power:,.0f} baht")
print(f"net per year {net:,.0f} baht")
print()
if net <= 0:
print("It never pays for itself. It goes backwards.")
else:
print(f"pays for the hardware in {spent * baht_per_usd / net:,.0f} years")
print()
# The comparison nobody runs. The money is the same money.
bought = spent / price["usd"]
print(f"The same {spent:.0f} USD spent on the coin itself buys "
f"{bought:.4f} XMR today.")
if xmr_a_year > 0:
print(f"The machine mines that much in {bought / xmr_a_year:,.0f} years.")
if __name__ == "__main__":
main()
🖥️ WHAT IT PRINTED · at list prices, 500 H/s
Raspberry Pi 5, 8GB 80.00 USD
AI HAT+ 2, 8GB 130.00 USD
power supply, case, card 40.00 USD
total 250.00 USD = 8,367 baht
mines per year 0.013062 XMR = 243 baht
power per year 355 baht
net per year -112 baht
It never pays for itself. It goes backwards.
The same 250 USD spent on the coin itself buys 0.4496 XMR today.
The machine mines that much in 34 years.
🇬🇧 English
Note what is in that parts list. The HAT is more than half the cost and contributes nothing.
Take it out and the same page reads very differently.
🇹🇭 ไทย
ดูรายการอะไหล่ให้ดี HAT คิดเป็นมากกว่าครึ่งของราคา และไม่ได้ช่วยอะไรเลย
เอามันออก แล้วหน้าเดียวกันนี้จะอ่านได้ต่างไปมาก
🇨🇳 中文
看看那张零件清单。HAT 占了一半以上的成本,而且一点贡献都没有。
把它去掉,同一页读起来就很不一样。
3What would have to be true? · อะไรถึงจะทำให้มันคุ้ม · 要什么条件才成立?
🇬🇧 English
Instead of arguing about whether it is worth it, solve for the number.
Four things could change. Ask what each would have to become, with the others left alone.
🇹🇭 ไทย
แทนที่จะเถียงกันว่าคุ้มหรือไม่คุ้ม ให้แก้สมการหาตัวเลข
มีสี่อย่างที่เปลี่ยนได้ ลองถามว่าแต่ละอย่างต้องกลายเป็นเท่าไหร่ โดยที่อย่างอื่นอยู่เฉย ๆ
🇨🇳 中文
与其争论值不值,不如把那个数解出来。
有四样东西可以变。问问每一样得变成多少,其余不动。
Show the answerดูเฉลย看答案
📄 breakeven1.py
"""breakeven1.py — challenge 3: what would have to be true for this to pay?
Rather than arguing about whether it is worth it, solve for the number.
Three of the four things are fixed by the world. Ask what each one would
have to become, with the others left alone.
"""
import json
import sys
import urllib.request
NETWORK = "https://localmonero.co/blocks/api/get_stats"
PRICE = "https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=usd,thb"
HASHRATE = 500.0
WATTS = 9.0
BAHT_PER_KWH = 4.5
BLOCKS_A_DAY = 720
ATOMIC = 1e12
sys.stdout.reconfigure(encoding="utf-8")
def get(url):
request = urllib.request.Request(url, headers={"User-Agent": "a lesson"})
with urllib.request.urlopen(request, timeout=30) as response:
return json.load(response)
def main():
chain = get(NETWORK)
price = get(PRICE)["monero"]
network, reward = chain["hashrate"], chain["last_reward"] / ATOMIC
power_a_day = WATTS * 24 / 1000 * BAHT_PER_KWH
earns_per_hash = BLOCKS_A_DAY * reward * price["thb"] / network
earns_a_day = HASHRATE * earns_per_hash
print(f"as things stand earns {earns_a_day:.2f} baht a day, "
f"power costs {power_a_day:.2f}")
print()
# Each of these leaves everything else exactly where it is.
need_hashrate = power_a_day / earns_per_hash
print(f"hashrate needed {need_hashrate:,.0f} H/s "
f"({need_hashrate / HASHRATE:.1f} times a Pi 5)")
xmr_a_day = BLOCKS_A_DAY * reward * (HASHRATE / network)
need_price = power_a_day / xmr_a_day
print(f"XMR price needed {need_price:,.0f} baht "
f"({need_price / price['thb']:.1f} times today)")
need_power = earns_a_day / (WATTS * 24 / 1000)
print(f"electricity needed {need_power:.2f} baht per kWh "
f"(you pay {BAHT_PER_KWH:.2f})")
need_watts = earns_a_day / (24 / 1000 * BAHT_PER_KWH)
print(f"or the same work at {need_watts:.1f} W "
f"(a Pi 5 under load draws about {WATTS:.0f})")
print()
print("None of those four is a small change. That is the answer.")
if __name__ == "__main__":
main()
🖥️ WHAT IT PRINTED · all four, from the same live data
as things stand earns 0.67 baht a day, power costs 0.97
hashrate needed 729 H/s (1.5 times a Pi 5)
XMR price needed 27,162 baht (1.5 times today)
electricity needed 3.09 baht per kWh (you pay 4.50)
or the same work at 6.2 W (a Pi 5 under load draws about 9)
🇬🇧 English
Those are all half-steps, not orders of magnitude. Running a Pi at these numbers is genuinely marginal.
Which is the honest answer, and a more useful one than either yes or no.
🇹🇭 ไทย
ทั้งหมดนั้นคือครึ่งก้าว ไม่ใช่ต่างกันเป็นเท่าตัวหลายเท่า การเดิน Pi ที่ตัวเลขแบบนี้ก้ำกึ่งจริง ๆ
ซึ่งคือคำตอบที่ซื่อตรง และมีประโยชน์กว่าการตอบว่าใช่หรือไม่
🇨🇳 中文
这些都是半步之差,不是数量级的差距。在这样的数字下跑一台 Pi,确实是边缘状态。
这才是诚实的答案,也比一句「行」或「不行」更有用。
🇬🇧 English
Six files, and the useful one is the arithmetic. Mining is a lottery with tickets priced in electricity.
The HAT cannot buy tickets. It is a good piece of hardware doing something else entirely, and there are pages here about that.
A Pi 5 with 8 GB and a Hailo-10H will run a small language model locally. That is what you bought.
🇹🇭 ไทย
หกไฟล์ และไฟล์ที่มีประโยชน์คือการคำนวณ การขุดคือลอตเตอรีที่ราคาตั๋วคิดเป็นค่าไฟ
HAT ซื้อตั๋วไม่ได้ มันเป็นฮาร์ดแวร์ที่ดีซึ่งทำอย่างอื่นไปเลย และมีหน้าอื่นในเว็บนี้ที่พูดถึงเรื่องนั้น
Pi 5 ขนาด 8 GB กับ Hailo-10H รันโมเดลภาษาเล็ก ๆ ในเครื่องได้ นั่นคือสิ่งที่คุณซื้อมา
🇨🇳 中文
六个文件,有用的是那套算术。挖矿是一场彩票,票价用电费结算。
HAT 买不了票。它是一块好硬件,只是在做完全另一件事,这个站上有别的页面讲那个。
一台 8 GB 的 Pi 5 配 Hailo-10H,能在本地跑一个小的语言模型。那才是你买的东西。
| You wantคุณอยากได้你想要 | Look upไปหาคำว่า去查 |
|---|---|
| What the HAT is forHAT มีไว้ทำอะไรHAT 是干嘛的 | Hailo runs 1 to 1.5 billion parameter modelsHailo รันโมเดลขนาด 1 ถึง 1.5 พันล้านพารามิเตอร์Hailo 能跑 10 到 15 亿参数的模型 |
| Your own measured hashrateแฮชเรตที่คุณวัดเอง你自己量到的算力 | xmrig --bench=1M |
| Mining something elseขุดอย่างอื่น挖点别的 | the same arithmetic, different constantsการคำนวณแบบเดียวกัน แค่เปลี่ยนค่าคงที่同一套算术,换几个常数 |
| Whether it is legal where you areมันถูกกฎหมายที่คุณอยู่ไหม在你那儿合不合法 | mining your own hardware usually is. Check anywayการขุดด้วยเครื่องของตัวเองมักจะได้ แต่ก็ควรตรวจสอบ用自己的硬件挖通常可以。还是查一下 |
🇬🇧 English
Next: what a small model actually does, running one on hardware you own, or the other coin, from Python.
🇹🇭 ไทย
ต่อไป: โมเดลเล็ก ๆ ทำอะไรได้บ้าง, รันมันบนเครื่องของคุณเอง หรือ อีกเหรียญหนึ่ง จาก Python
🇨🇳 中文
接下来:小模型到底能做什么、在你自己的硬件上跑一个,或者另一种币,用 Python。