Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a test with classes and lists #35

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/run_benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Install development version of pyccel from GitHub
run: |
pip3 install --upgrade pip
pip3 install 'pyccel @ git+https://github.com/pyccel/pyccel'
pip3 install 'pyccel @ git+https://github.com/pyccel/pyccel@test_pasc_branch'
- name: Install python dependencies
run: |
pip3 install .
Expand Down
52 changes: 27 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,38 +89,40 @@ 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 Tue Dec 10 10:35:43 UTC 2024)
### Performance Comparison (as of Sun Dec 15 11:01:13 UTC 2024)
## Compilation time
Algorithm | python | pythran_gnu | pythran_intel | numba | pyccel_fortran_gnu | pyccel_c_gnu | pyccel_fortran_intel | pyccel_c_intel
------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | -------------------------
Ackermann | - | 2.34 | 2.13 | 0.34 | 1.34 | 1.30 | 1.42 | 1.39
Bellman Ford | - | 3.44 | 3.69 | 1.08 | 3.64 | 3.97 | 3.80 | 4.04
Dijkstra | - | 2.40 | 2.70 | 1.60 | 3.70 | 4.01 | 3.96 | 4.12
Euler | - | 2.81 | 3.17 | 2.06 | 3.75 | 3.99 | 3.79 | 3.98
Midpoint Explicit | - | 3.20 | 3.50 | 3.10 | 3.95 | 4.24 | 4.05 | 4.19
Midpoint Fixed | - | 3.72 | 4.08 | 3.38 | 4.10 | 4.33 | 4.17 | 4.36
RK4 | - | 3.82 | 4.33 | 3.85 | 4.46 | 4.69 | 4.53 | 4.80
FD - L Convection | - | 2.41 | 2.77 | 0.94 | 1.49 | 4.06 | 1.65 | 4.09
FD - NL Convection | - | 3.42 | 3.70 | 0.92 | 1.42 | 3.99 | 1.66 | 3.94
FD - Poisson | - | 3.46 | 3.77 | 1.37 | 1.59 | 4.08 | 2.85 | 3.99
FD - Laplace | - | 6.68 | 8.16 | 3.17 | 1.84 | 4.46 | 2.14 | 4.40
M-D | - | 6.60 | 6.94 | 4.14 | - | - | - | -
Ackermann | - | 2.30 | 2.12 | 0.33 | 1.32 | 1.32 | 1.45 | 1.39
Bellman Ford | - | 3.41 | 3.68 | 1.08 | 3.70 | 3.93 | 3.78 | 3.93
Dijkstra | - | 2.38 | 2.66 | 1.56 | 3.71 | 3.98 | 3.89 | 4.04
Dijkstra with heap class | - | - | - | - | 4.23 | 4.09 | 4.61 | 4.11
Euler | - | 2.66 | 3.04 | 2.01 | 3.61 | 3.94 | 3.77 | 3.98
Midpoint Explicit | - | 3.04 | 3.43 | 2.99 | 3.85 | 4.18 | 3.98 | 4.17
Midpoint Fixed | - | 3.54 | 3.95 | 3.22 | 3.95 | 4.26 | 4.09 | 4.27
RK4 | - | 3.72 | 4.22 | 3.74 | 4.33 | 4.62 | 4.44 | 4.64
FD - L Convection | - | 2.31 | 2.65 | 0.87 | 1.40 | 3.93 | 1.59 | 3.93
FD - NL Convection | - | 3.29 | 3.54 | 0.88 | 1.41 | 3.92 | 1.62 | 3.91
FD - Poisson | - | 3.38 | 3.64 | 1.33 | 1.53 | 4.03 | 2.84 | 4.00
FD - Laplace | - | 6.49 | 7.97 | 3.01 | 1.82 | 4.34 | 2.10 | 4.28
M-D | - | 6.41 | 6.74 | 4.03 | - | - | - | -

## Execution time
Algorithm | python | pythran_gnu | pythran_intel | numba | pyccel_fortran_gnu | pyccel_c_gnu | pyccel_fortran_intel | pyccel_c_intel
------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- | -------------------------
Ackermann (ms) | 294.00 | 2.85 | 3.03 | 9.76 | 1.49 | 1.55 | 10.40 | 4.35
Bellman Ford (ms) | 1760.00 | 5.17 | 3.43 | 3.77 | 2.87 | 5.98 | - | 19.20
Dijkstra (ms) | 4900.00 | 26.10 | 17.00 | 19.70 | 19.30 | 31.00 | - | 23.40
Euler (ms) | 3920.00 | 25.30 | 25.80 | 38.30 | 14.80 | 145.00 | 13.70 | 128.00
Midpoint Explicit (ms) | 7980.00 | 52.50 | 51.40 | 77.40 | 23.90 | 281.00 | 16.80 | 250.00
Midpoint Fixed (ms) | 41200.00 | 251.00 | 92.60 | 374.00 | 75.60 | 1400.00 | 61.00 | 1200.00
RK4 (ms) | 19900.00 | 158.00 | 35.60 | 138.00 | 34.20 | 481.00 | 38.60 | 405.00
FD - L Convection (ms) | 2260.00 | 1.63 | 1.62 | 2.68 | 1.51 | 1.63 | - | 4.08
FD - NL Convection (ms) | 2710.00 | 1.88 | 1.63 | 2.83 | 1.97 | 2.02 | - | 4.08
FD - Poisson (ms) | 6150.00 | 2.95 | 5.46 | 7.20 | 2.77 | 3.72 | - | 4.93
FD - Laplace (ms) | 575.00 | 64.20 | 143.00 | 246.00 | 58.50 | 255.00 | - | 274.00
M-D (ms) | 14800.00 | 15.20 | 53.10 | 59.30 | - | - | - | -
Ackermann (ms) | 292.00 | 2.86 | 3.04 | 9.60 | 1.55 | 1.55 | 10.10 | 4.33
Bellman Ford (ms) | 1750.00 | 5.22 | 3.41 | 3.90 | 2.94 | 6.09 | - | 18.90
Dijkstra (ms) | 4870.00 | 25.30 | 16.80 | 18.90 | 18.30 | 29.30 | - | 21.00
Dijkstra with heap class (ms) | 8920.00 | - | - | - | 264.00 | 102.00 | - | 107.00
Euler (ms) | 3790.00 | 25.60 | 25.40 | 36.90 | 14.40 | 141.00 | 13.80 | 127.00
Midpoint Explicit (ms) | 7630.00 | 52.70 | 51.20 | 78.00 | 22.10 | 279.00 | 16.20 | 251.00
Midpoint Fixed (ms) | 39500.00 | 252.00 | 92.50 | 376.00 | 74.40 | 1400.00 | 58.90 | 1200.00
RK4 (ms) | 21000.00 | 161.00 | 36.80 | 139.00 | 31.50 | 485.00 | 38.40 | 402.00
FD - L Convection (ms) | 2260.00 | 1.63 | 1.60 | 2.67 | 1.54 | 1.85 | - | 4.06
FD - NL Convection (ms) | 2720.00 | 1.82 | 1.62 | 2.77 | 1.83 | 2.03 | - | 4.09
FD - Poisson (ms) | 6020.00 | 2.95 | 5.45 | 7.10 | 2.75 | 3.84 | - | 4.95
FD - Laplace (ms) | 578.00 | 64.70 | 143.00 | 244.00 | 58.10 | 280.00 | - | 273.00
M-D (ms) | 14600.00 | 15.30 | 52.90 | 58.90 | - | - | - | -

![Development compilation results](./version_specific_results/devel_performance_310_compilation.svg)
![Development execution results](./version_specific_results/devel_performance_310_execution.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 @@ -82,6 +82,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 @@ -181,6 +186,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 @@ -200,6 +207,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 @@ -273,6 +281,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