Machine Learning Primer -- Python Tutorial




Claudius Gros, WS 2024/25

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

Acceleration

never use loops

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

import torch

nMatrix = 50
nRow    = 40
nCol    = 30
nS      = 20

AA = torch.randn(nMatrix,nRow,nCol)             # combine many matrices
BB = torch.randn(nMatrix,nCol,nS  )             # to a single tensor

YY = torch.zeros(nMatrix,nRow,nS)   
if (1==1): 
  YY = torch.matmul(AA,BB)                      # tensor operation
else:
  for ii in range(nMatrix):                     # looping over all matrices
    for nn in range(nRow):          
      for mm in range(nS):          
        for ll in range(nCol):                  # explicit multiplication
           YY[ii][nn][mm] += AA[ii][nn][ll]*BB[ii][ll][mm]
#
print()
print("AA", AA.shape)
print("BB", BB.shape)
print("YY", YY.shape)
print()
print(f'we did multiply {nMatrix:d} matrices')
print(f'of type ({nRow:d}x{nCol:d}) and ({nCol:d}x{nS:d})')

basic threading

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

import threading   # nomen est omen
import time        # sleep, etc.

#
# function to run asynchronous
#
def do_work(tNumber=0):
    print("starting  thread # %s", tNumber)
    rr = 1.0
    if (tNumber==0):
      time.sleep(10)             # sleeping 10 seconds
    else:
      while (1==1):              # doing heavy stuff
        rr = 1.0/(1.0+rr)
    print("finishing thread # %s", tNumber)

#
# main
#
allThreads = list()
for i in range(5):
  x =threading.Thread(target=do_work, args=(i,))
  allThreads.append(x)
  x.start()                      # starting thread 
#
for i in range(len(allThreads)):
  allThreads[i].join()           # waiting for threads to finish
#
print("\n# all done folks")

automatic threading

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

import torch
import os                          # operating system

nMatrix = 500
nRow    = 400
nCol    = 300
nS      = 200

torch.set_num_threads(1)           # for cpu-based hardware
nCPU = os.cpu_count()              # number of available cpu
if (nCPU>2): 
  torch.set_num_threads(nCPU-2)    # leave two for other uses
#
print("\n# number of CPU, threads: ",nCPU,torch.get_num_threads()) 
#
AA = torch.randn(nMatrix,nRow,nCol)            
BB = torch.randn(nMatrix,nCol,nS  )        
#
for ii in range(1000):             # do heavy stuff
  if (ii%50==0):
    print(ii)
  YY = torch.matmul(AA,BB)    

exponential forking

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

import os                         # underlying operation system

aa = 10
print()
print(f"main PID:", os.getpid())  # pid of main
print()

newPid = os.fork()                # forking 
myPid = os.getpid()               # pid after forking

aa = aa + 2
print(f"   myPID: {myPid:6d},  newPid: {newPid:6d},                    aa: {aa:6d}")

newNewPid = os.fork()
myPid = os.getpid()

aa = aa + 10
print(f"   myPID: {myPid:6d},  newPid: {newPid:6d}, newNewPid: {newPid:6d}, aa: {aa:6d}")