Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 27 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,41 @@ Solves a 2D Laplace problem using Finite Differences methods. The code is adapte

Runs a molecular dynamics simulation. The code is adapted from examples written by [J. Burkardt](https://people.sc.fsu.edu/~jburkardt/py_src/py_src.html)
## Development branch results
### Performance Comparison (as of Fri Jun 27 09:07:43 UTC 2025)
### Performance Comparison (as of Fri Jun 27 11:43:23 UTC 2025)
## Compilation time
Algorithm | python | pythran_gnu | pythran_intel | numba | pyccel_gnu_c | pyccel_gnu_fortran | pyccel_intel_c | pyccel_intel_fortran
------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | -------------------------
Ackermann | - | 2.36 | 2.04 | 0.27 | 1.33 | 1.35 | 1.33 | 1.39
Bellman Ford | - | 3.37 | 3.65 | 0.94 | 1.62 | 1.50 | 1.56 | 1.55
Dijkstra | - | 2.35 | 2.62 | 1.20 | 1.72 | 1.60 | 1.67 | 1.69
Euler | - | 2.59 | 2.95 | 3.30 | 1.57 | 1.46 | 1.55 | 1.52
Midpoint Explicit | - | 2.93 | 3.32 | 3.63 | 1.83 | 1.70 | 1.75 | 1.76
Midpoint Fixed | - | 3.27 | 3.63 | 3.71 | 1.88 | 1.75 | 1.80 | 1.81
RK4 | - | 3.43 | 3.88 | 3.71 | 2.21 | 2.14 | 2.11 | 2.16
FD - L Convection | - | 2.28 | 2.61 | 2.43 | 1.54 | 1.44 | 1.48 | 1.48
FD - NL Convection | - | 3.23 | 3.54 | 2.43 | 1.53 | 1.43 | 1.50 | 1.48
FD - Poisson | - | 3.41 | 3.67 | 5.59 | 1.66 | 1.70 | 1.63 | 1.87
FD - Laplace | - | 6.79 | 7.50 | 6.94 | 1.90 | 1.85 | 1.80 | 1.96
M-D | - | 6.16 | 6.10 | 8.36 | 2.33 | 2.46 | 2.22 | 2.53
Ackermann | - | 2.34 | 2.21 | 0.28 | 1.35 | 1.36 | 1.35 | 1.44
Bellman Ford | - | 3.35 | 3.61 | 0.93 | 1.63 | 1.50 | 1.56 | 1.56
Dijkstra | - | 2.34 | 2.60 | 1.22 | 1.72 | 1.62 | 1.65 | 1.69
Dijkstra with heap class | - | - | - | - | - | - | - | -
Euler | - | 2.62 | 2.98 | 3.31 | 1.58 | 1.48 | 1.53 | 1.53
Midpoint Explicit | - | 2.92 | 3.32 | 3.59 | 1.81 | 1.70 | 1.76 | 1.74
Midpoint Fixed | - | 3.31 | 3.68 | 3.69 | 1.90 | 1.78 | 1.82 | 1.81
RK4 | - | 3.43 | 3.87 | 3.74 | 2.24 | 2.16 | 2.14 | 2.18
FD - L Convection | - | 2.29 | 2.59 | 2.45 | 1.54 | 1.44 | 1.48 | 1.49
FD - NL Convection | - | 3.23 | 3.59 | 2.45 | 1.54 | 1.46 | 1.50 | 1.50
FD - Poisson | - | 3.44 | 3.65 | 5.64 | 1.67 | 1.71 | 1.62 | 1.87
FD - Laplace | - | 6.86 | 7.48 | 7.04 | 1.92 | 1.87 | 1.82 | 1.94
M-D | - | 6.18 | 6.15 | 8.44 | 2.36 | 2.47 | 2.26 | 2.57
Splines | - | - | - | 0.58 | - | - | - | -

## Execution time
Algorithm | python | pythran_gnu | pythran_intel | numba | pyccel_gnu_c | pyccel_gnu_fortran | pyccel_intel_c | pyccel_intel_fortran
------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | -------------------------
Ackermann (ms) | 409.00 | 2.92 | 3.05 | 9.82 | 1.23 | 1.32 | 4.00 | 9.63
Bellman Ford (ms) | 1680.00 | 5.25 | 3.49 | 3.83 | 3.74 | 3.26 | 6.44 | 4.42
Dijkstra (ms) | 4750.00 | 21.00 | 17.10 | 19.30 | 67.00 | 19.00 | 69.20 | 22.20
Euler (ms) | 3380.00 | 25.30 | 25.20 | 36.40 | 26.40 | 10.60 | 26.80 | 15.10
Midpoint Explicit (ms) | 6860.00 | 50.90 | 50.80 | 69.00 | 45.20 | 18.90 | 45.90 | 16.00
Midpoint Fixed (ms) | 34500.00 | 268.00 | 91.90 | 323.00 | 190.00 | 71.90 | 354.00 | 51.30
RK4 (ms) | 17100.00 | 153.00 | 36.00 | 127.00 | 95.80 | 32.30 | 90.40 | 28.00
FD - L Convection (ms) | 2130.00 | 1.55 | 1.60 | 5.63 | 6.63 | 1.51 | 7.74 | 1.56
FD - NL Convection (ms) | 2640.00 | 2.02 | 1.65 | 5.65 | 6.66 | 1.59 | 8.02 | 1.40
FD - Poisson (ms) | 5460.00 | 2.97 | 5.33 | 6.74 | 16.10 | 2.63 | 24.00 | 2.60
FD - Laplace (ms) | 623.00 | 66.80 | 127.00 | 274.00 | 484.00 | 61.30 | 656.00 | 59.50
M-D (ms) | 14300.00 | 36.10 | 52.50 | 60.60 | 114.00 | 62.40 | 62.00 | 89.40
Ackermann (ms) | 415.00 | 2.91 | 3.05 | 9.65 | 1.23 | 1.27 | 4.01 | 8.66
Bellman Ford (ms) | 1680.00 | 5.24 | 3.48 | 3.92 | 3.81 | 3.22 | 5.83 | 4.28
Dijkstra (ms) | 4810.00 | 20.60 | 17.10 | 18.60 | 64.10 | 18.70 | 65.40 | 22.20
Dijkstra with heap class (s) | 6.58 | - | - | - | - | - | - | -
Euler (ms) | 3410.00 | 25.20 | 25.30 | 35.90 | 27.30 | 10.60 | 26.60 | 16.20
Midpoint Explicit (ms) | 6900.00 | 51.60 | 50.90 | 70.80 | 57.10 | 19.00 | 45.60 | 16.20
Midpoint Fixed (ms) | 35500.00 | 266.00 | 92.00 | 323.00 | 190.00 | 72.00 | 198.00 | 52.00
RK4 (ms) | 17200.00 | 151.00 | 36.60 | 127.00 | 94.90 | 31.60 | 92.30 | 29.10
FD - L Convection (ms) | 2100.00 | 1.52 | 1.61 | 5.67 | 7.66 | 1.64 | 7.62 | 1.49
FD - NL Convection (ms) | 2620.00 | 1.84 | 1.77 | 5.65 | 6.82 | 1.75 | 8.54 | 1.53
FD - Poisson (ms) | 5770.00 | 2.91 | 5.39 | 6.68 | 16.00 | 2.64 | 23.70 | 2.59
FD - Laplace (ms) | 650.00 | 66.10 | 127.00 | 276.00 | 491.00 | 59.90 | 664.00 | 58.90
M-D (ms) | 14400.00 | 35.90 | 52.30 | 60.00 | 117.00 | 62.60 | 61.00 | 88.80
Splines (s) | 1.66 | - | - | 0.02 | - | - | - | -

![Development compilation results](./version_specific_results/devel_performance_311_compilation.svg)
Expand Down
9 changes: 9 additions & 0 deletions benchmarks/run_benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
['dijkstra_distance_test'],
'',
'd = dijkstra_distance_test()'),
TestInfo('Dijkstra with heap class',
'dijkstra_heap.py',
['dijkstra'],
'from setup_tools import setup_sparse_dijkstra; graph, start, num_nodes, max_neighbours = setup_sparse_dijkstra()',
'd = dijkstra(graph, start, num_nodes, max_neighbours)'),
TestInfo('Euler',
'euler_mod.py',
['euler_humps_test'],
Expand Down Expand Up @@ -191,6 +196,8 @@ def run_process(cmd: "List[str]", time_compilation: "bool"=False, env = None):
])
return returncode, out, err, cpu_time

setup_basename = 'setup_tools.py'
setup_file = os.path.join(code_folder, setup_basename)

for t in tests:
print("===========================================", file=log_file, flush=True)
Expand All @@ -210,6 +217,7 @@ def run_process(cmd: "List[str]", time_compilation: "bool"=False, env = None):
os.makedirs(new_folder, exist_ok=True)
shutil.copyfile(test_file, os.path.join(new_folder, basename))
shutil.copyfile(numba_test_file, os.path.join(new_folder, numba_basename))
shutil.copyfile(setup_file, os.path.join(new_folder, setup_basename))
os.chdir(new_folder)

import_funcs = ', '.join(t.imports)
Expand Down Expand Up @@ -284,6 +292,7 @@ def run_process(cmd: "List[str]", time_compilation: "bool"=False, env = None):
run_times.append(None)
run_units.append(None)
print(err, file=log_file, flush=True)
continue
else:
print("Compilation Process time : ",out, file=log_file, flush=True)
comp_times.append('{:.2f}'.format(float(out)))
Expand Down
94 changes: 94 additions & 0 deletions benchmarks/tests/dijkstra_heap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import numpy as np

class MinHeap:
def __init__(self):
self.distances: 'list[int]' = []
self.nodes: 'list[int]' = []

def _sift_up(self, index: int):
parent = (index - 1) // 2
if index > 0 and self.distances[index] < self.distances[parent]:
tmp = self.distances[index]
self.distances[index] = self.distances[parent]
self.distances[parent] = tmp
tmp = self.nodes[index]
self.nodes[index] = self.nodes[parent]
self.nodes[parent] = tmp
self._sift_up(parent)

def _sift_down(self, index: int):
left = 2 * index + 1
right = 2 * index + 2
smallest = index

if left < len(self.distances) and self.distances[left] < self.distances[smallest]:
smallest = left
if right < len(self.distances) and self.distances[right] < self.distances[smallest]:
smallest = right

if smallest != index:
tmp = self.distances[index]
self.distances[index] = self.distances[smallest]
self.distances[smallest] = tmp
tmp = self.nodes[index]
self.nodes[index] = self.nodes[smallest]
self.nodes[smallest] = tmp
self._sift_down(smallest)

def push(self, item_distance: 'int', item_node: 'int'):
self.distances.append(item_distance)
self.nodes.append(item_node)
self._sift_up(len(self.distances) - 1)

def pop(self):
if len(self.distances) == 1:
return self.distances.pop(), self.nodes.pop()
root_distance = self.distances[0]
root_node = self.nodes[0]
self.distances[0] = self.distances.pop()
self.nodes[0] = self.nodes.pop()
self._sift_down(0)
return root_distance, root_node


def length(self) -> int:
return len(self.distances)

def dijkstra(graph: 'int[:,:]', start: int, num_nodes: int, max_neighbors: int) -> 'int[:]':
"""
Implements Dijkstra's algorithm to find the shortest paths from a start node.

Parameters:
graph (numpy array): A 2D numpy array where each row represents a node and contains up to 5 neighbors as pairs (neighbor, weight). -1 indicates no neighbor.
start (int): The starting node index.
num_nodes (int): Total number of nodes in the graph.

Returns:
numpy array: Shortest distances from the start node to each node.
"""
priority_queue = MinHeap()
shortest_distances = np.full(num_nodes, int(1e9))
shortest_distances[start] = 0

priority_queue.push(0, start)

while priority_queue.length() > 0:
current_distance, current_node = priority_queue.pop()

if current_distance > shortest_distances[current_node]:
continue

for i in range(0, 2 * max_neighbors, 2):
neighbor = graph[current_node, i]
weight = graph[current_node, i + 1]
if neighbor == -1 or current_node == neighbor:
continue

dist = current_distance + weight

if dist < shortest_distances[neighbor]:
shortest_distances[neighbor] = dist
priority_queue.push(dist, neighbor)

return shortest_distances

Loading