Pico übertakten

Ein Kollege fragte mich: „Kann man eigentlich auch den Raspberry Pi Pico übertakten?“. Ich konnte nur ihm nur versprechen, das herauszufinden.

Raspberry Pi Pico übertakten
Olli Graf - raspithek.de
pico-boardCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Ein Raspberry Pi Pico

Grundlagen

Die Grundlagen zur Übertaktung sind von den des Raspberry Pi 4B nicht sonderlich verschieden. Die zwei Kerne ARM Cortex M0+ des RP2040 Microcontroller sind ab Werk mit 125MHz getaktet.

Material

Ich benutze in diesem Post folgendes Material:

  • Raspberry Pi Pico
  • Datenkabel USB-A auf µUSB
  • Kühlkörper zum Aufkleben

Mein größtes Problem war zunächst, ein µ-USB Datenkabel zu finden. Die meisten Kabel in meinem Bestand dienten mal zum Laden irgendwelcher Handys.

Der Pico wird mit MicroPython geflasht.

Warnung: Ein höherer Takt kann den Pico unter Umständen beschädigen! Die Raspberry Pi Foundation stellt sich in so einem Fall von der Garantie aus.

Pico übertakten

Im Gegensatz zum Raspi 4A gibt es beim Pico keine config.txt, in der wir die Taktfrequenz konfigurieren können. Daher ist jedes Programm selber verantwortlich, die Frequenz zu setzen.

Die Methode freq() , die wir dafür benötigen, liegt im machine Package. Ohne Parameter liefert diese Methode den aktuell eingestellten Takt in Hz zurück. Wir können ihr aber auch die gewünschte Frequenz (ebenfalls in Hz) übergeben.

Was wir jetzt brauchen ist eine Berechnung, die die CPU richtig unter Last setzt. Dazu eignet sich die Berechnung von Primzahlen mit dem Sieb des Eratosthenes. Der Algorithmus ist nicht unbedingt optimal, aber darum geht es hier nicht.

#Berechnung von Primzahlen mit dem Sieb des Eratosthenes.

def sieb_des_eratosthenes(limit):
  # Erzeuge eine Liste, die angibt, ob eine Zahl eine Primzahl ist
  is_prime = [True] * (limit + 1)
  p = 2

  while (p * p <= limit):
      # Wenn is_prime[p] nicht verändert wurde, ist p eine Primzahl
    if is_prime[p]:
    # Alle Vielfachen von p können keine Primzahl sein.
      for i in range(p * p, limit + 1, p):
        is_prime[i] = False
        p += 1

    # Sammle alle Primzahlen in einer Liste.
    prime_numbers = [p for p in range(2, limit + 1) if is_prime[p]]
    return prime_numbers

Diese Methode wird von einer Methode gekapselt, die die Laufzeit auswertet.

# Methode zur Laufzeitbestimmung
def berechnung(limit):
  ergebnis = {}
  
  start_time = time.ticks_ms()
  
  prime_numbers = sieb_des_eratosthenes(limit)
  
  ergebnis['primzahlen'] = prime_numbers
  
  end_time = time.ticks_ms()
  
  running_time =time.ticks_diff(end_time,start_time)
  ergebnis['laufzeit'] = running_time
  
  return ergebnis

Die Methode liefert ein Dictionary mit zwei Einträgen zurück. In 'primzahlen' befindet sich die Liste der berechneten Primzahlen, in 'laufzeit' ist die Laufzeit der Berechnung in ms abgelegt.

Das Hauptprogramm führt die Berechnung zweimal durch, zunächst mit dem Standardtakt von 125MHz, danach mit 270MHz. Vor der Taktumschaltung blinkt die LED auf dem Pico kurz auf, um die Umschaltung zu signalisieren.

# sieve_oc.py
import time
import machine
from machine import Pin

led = Pin(25, Pin.OUT)

#Berechnung von Primzahlen mit dem Sieb des Eratosthenes.

def sieb_des_eratosthenes(limit):
  # Erzeuge eine Liste, die angibt, ob eine Zahl eine Primzahl ist
  is_prime = [True] * (limit + 1)
  p = 2

  while (p * p <= limit):
      # Wenn is_prime[p] nicht verändert wurde, ist p eine Primzahl
    if is_prime[p]:
    # Alle Vielfachen von p können keine Primzahl sein.
      for i in range(p * p, limit + 1, p):
        is_prime[i] = False
        p += 1

    # Sammle alle Primzahlen in einer Liste.
    prime_numbers = [p for p in range(2, limit + 1) if is_prime[p]]
    return prime_numbers

# Methode zur Laufzeitbestimmung

def berechnung(limit):
  ergebnis = {}
  
  start_time = time.ticks_ms()
  
  prime_numbers = sieb_des_eratosthenes(limit)
  
  ergebnis['primzahlen'] = prime_numbers
  
  end_time = time.ticks_ms()
  
  running_time =time.ticks_diff(end_time,start_time)
  ergebnis['laufzeit'] = running_time
  
  return ergebnis
  
# Liefert den Clock-Speed in MHz
def get_speed():
  return str(round(machine.freq()/1000000,1))
               
# Beispielverwendung: Finde alle Primzahlen bis 1000

print(f'Durchgang #1 mit {get_speed()}MHz')

limit = 10000
ergebnis1 = berechnung(limit)
laufzeit1 = ergebnis1['laufzeit']


print(f'Laufzeit: {laufzeit1}ms')

#Übertaktung auf 270MHz
led.on()
machine.freq(270000000)
print(f'Durchgang #2 mit {get_speed()}MHz')
ergebnis2 = berechnung(limit)

Stromverbrauch

Ein höherer Takt zieht immer auch eine höhere Stromaufnahme mit sich.

Ohne Übertaktung zeigt mir das zwischen Pico und Powerbank geschaltete Messgerät eine Spannung von 5,02V bei 0,03A Stromaufnahme an. Mit Übertaktung steigt die Spannung auf 5,1V bei 0,02A Stromverbrauch. Allerdings schwankt der Stromverbrauch gelegentlich, da der Pico nicht immer 100% Last hat.

In einer Situation, in der der Pico mit einem Akku betrieben wird, könnte das ins Gewicht fallen.

Fazit

In einer Situation, in der du auf eine höhere Rechenleistung des Pico angewiesen bist, kannst du programmatisch denTakt der beiden Kerne erhöhen.Ich würde dies aber immer nur situativ machen und danach wieder auf den Standardtakt zurückschalten.

MicroPython lässt einen höheren Takt als 275Mhz nicht zu. Die Methode machine_freq() kommt bei höheren Werten nicht zurück. Vermutlich, um den Pico vor Beschädigung zu schützen.

Overclocking Spezialisten, die lange nach einem geeigneten Pico mit dem perfekten SoC suchen haben den Pico sogar auf 3GHz getaktet. Ich bezweifle aber, dass dann die I/O Kanäle noch richtig funktionieren.

Ich will hier keinen neuen Rekord aufstellen, sondern dir nur zeigen, wie es geht.

Schreibe einen Kommentar

Creative Commons License
Except where otherwise noted, the content on this site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Olli Graf - raspithek.de
WordPress Cookie Hinweis von Real Cookie Banner