dric2018 commited on
Commit
8f062e6
verified
1 Parent(s): e327e52

init tracker

Browse files
Files changed (6) hide show
  1. Dockerfile +15 -0
  2. app.py +137 -0
  3. config.py +6 -0
  4. data.json +115 -0
  5. requirements.txt +5 -0
  6. utils.py +16 -0
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /src
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /src
13
+ COPY --chown=user . /src
14
+
15
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from config import Config as cfg
2
+
3
+ import dash
4
+ from dash import dcc, html
5
+ from dash.dependencies import Input, Output
6
+
7
+ import json
8
+
9
+ import pandas as pd
10
+
11
+ import plotly.graph_objects as go
12
+
13
+ from utils import flatten_json
14
+
15
+ # Load data
16
+ with open(cfg.data_path, "r") as f:
17
+ data = f.read()
18
+ data = json.loads(data)
19
+
20
+ flattened_data = [flatten_json(d) for d in data]
21
+ df = pd.DataFrame(flattened_data)
22
+
23
+ def get_info(idx:int, df):
24
+ name = df.loc[idx, "name"]
25
+ country = df.loc[idx, "location_country"]
26
+ n_gpus = df.loc[idx, "capacity_n_GPUs"]
27
+ gpu_type = df.loc[idx, "capacity_GPU_type"]
28
+ addr = df.loc[idx, "location_address"]
29
+ last_update = df.loc[idx, "last_update"]
30
+ capacity = df.loc[idx, "capacity_pflops_performance"]
31
+ url = df.loc[idx, "contact_info_website"]
32
+ info = dcc.Markdown(
33
+ f"""
34
+ {country}
35
+ {name} - **{str(n_gpus)}x{gpu_type}**
36
+ Overall Performance: **{capacity} petaFLOPS**
37
+ ({last_update})
38
+ {addr}
39
+ Website: {url}
40
+ """,
41
+ style={"white-space": "pre"}
42
+ )
43
+ return info
44
+
45
+ # Map
46
+ fig = go.Figure(data=go.Choropleth(
47
+ locations=df['location_CN'],
48
+ z = df['capacity_pflops_performance'],
49
+ zmax=10,
50
+ zmin=0,
51
+ locationmode = 'ISO-3',
52
+ colorscale = 'reds',
53
+ # text=df["info"],
54
+ colorbar=dict(
55
+ title='Compute capability (petaFLOPS)', # Title for your colorbar
56
+ orientation='h', # Set orientation to horizontal
57
+ thickness=5, # Adjust thickness as needed
58
+ )
59
+ ))
60
+
61
+ fig.update_layout(
62
+ geo_scope='africa',
63
+ height=400,
64
+ #margin={"r": 0, "t": 0, "l": 0, "b": 0},
65
+ margin={"r": 0, "t": 0, "b": 0},
66
+ autosize=True,
67
+ # paper_bgcolor='beige' # Background color of the entire figure
68
+ dragmode=False
69
+
70
+ )
71
+ fig.update_geos(
72
+ landcolor="white", # Sets the color of land areas
73
+ oceancolor="lightblue", # Sets the color of ocean areas
74
+ subunitcolor="darkgray", # Sets the color of country subdivisions
75
+ lakecolor="lightblue", # Set lake color to blue
76
+ rivercolor="lightblue",
77
+ showlakes=True,
78
+ showrivers=True, # Make lakes visible
79
+ showland=True,
80
+ showocean=True,
81
+ showsubunits=True,
82
+ resolution=50,
83
+ )
84
+
85
+ # App
86
+
87
+ external_stylesheets = ["https://fonts.googleapis.com/css2?family=Tahoma&display=swap"]
88
+ app = dash.Dash("Africa HPC Tracker", external_stylesheets=external_stylesheets)
89
+ server = app.server
90
+
91
+ TITLE_COLOR = "#095C73"
92
+ DETAILS_COLOR = "#0F718E"
93
+
94
+ app.layout = html.Div(
95
+ id="parent_div",
96
+ children=[
97
+ html.H1(
98
+ id='header-text',
99
+ children='Africa HPC Tracker',
100
+ style={'color':TITLE_COLOR}
101
+ ),
102
+ html.Div(
103
+ id='hover-info',
104
+ style={'color':DETAILS_COLOR}
105
+ ),
106
+ dcc.Graph(
107
+ id='hpc-tracker',
108
+ figure=fig
109
+ ),
110
+
111
+ ],
112
+ style={
113
+ 'textAlign' : 'center',
114
+ 'font-family' : 'Arial, sans-serif',
115
+ }
116
+ )
117
+
118
+ # Callbacks
119
+
120
+ @app.callback(
121
+ Output('hover-info', 'children'),
122
+ Input('hpc-tracker', 'hoverData'))
123
+
124
+ def display_hover_data(hoverData):
125
+ if hoverData:
126
+ # Access hovered point data and display or modify other elements
127
+ idx = hoverData['points'][0]['pointIndex']
128
+ return get_info(idx, df)
129
+ return "Hover over a region to display the details"
130
+
131
+ if __name__ == '__main__':
132
+ app.run(
133
+ host=cfg.HOST,
134
+ port=cfg.PORT,
135
+ debug=cfg.IS_DEBUG,
136
+ dev_tools_ui=cfg.IS_DEBUG
137
+ )
config.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+
2
+ class Config:
3
+ data_path = "data.json"
4
+ HOST = "0.0.0.0"
5
+ PORT = 8050
6
+ IS_DEBUG = True
data.json ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [{
2
+ "name": "Taouey",
3
+ "location": {
4
+ "country": "Senegal",
5
+ "CN": "SEN",
6
+ "city": "Diamniadio",
7
+ "coordinates": {"lat": 14.70721512041391, "lng": -17.419260299665588},
8
+ "region": "West",
9
+ "address": "Cit茅 du Savoir, Diamniadio, Dakar"
10
+
11
+ },
12
+ "type": "National HPC",
13
+ "status": "Live",
14
+ "capacity": {
15
+ "GPU_type": "V100",
16
+ "n_GPUs": 48,
17
+ "pflops_performance": 0.5376
18
+ },
19
+ "contact_info": {
20
+ "website": "https://cineri.sn/"
21
+ },
22
+ "last_update": "2019"
23
+ },
24
+ {
25
+ "name": "Toubkal (GPU Cluster)",
26
+ "location": {
27
+ "country": "Morocco",
28
+ "CN": "MAR",
29
+ "city": "Ben Guerir",
30
+ "coordinates": {"lat": 32.217507573027476, "lng": -7.938512605642216},
31
+ "region": "North",
32
+ "address": "Mohammed VI Polytechnic University, Ben Guerir 43150"
33
+ },
34
+ "type": "National HPC",
35
+ "status": "Live",
36
+ "capacity": {
37
+ "GPU_type": "A100",
38
+ "n_GPUs": 20,
39
+ "pflops_performance": 6.24
40
+ },
41
+ "contact_info": {
42
+ "website": "https://toubkal.um6p.ma/"
43
+ },
44
+ "last_update": "2021"
45
+ },
46
+ {
47
+ "name": "CNCCI",
48
+ "location": {
49
+ "country": "C么te d'Ivoire",
50
+ "city": "Abidjan",
51
+ "CN": "CIV",
52
+ "coordinates": {"lat": 5.358842210111155, "lng": -3.902231013281939},
53
+ "region": "West",
54
+ "address": "P么le Scientifique et d'Innovation de Bingerville (PSI), Abidjan"
55
+
56
+ },
57
+ "type": "National HPC",
58
+ "status": "Live",
59
+ "capacity": {
60
+ "GPU_type": "K80",
61
+ "n_GPUs": 24,
62
+ "pflops_performance": 0.3226
63
+ },
64
+ "contact_info": {
65
+ "website": "https://cncci.edu.ci/cncci/"
66
+ },
67
+ "last_update": "2018"
68
+ },
69
+ {
70
+ "name": "Lengau",
71
+ "location": {
72
+ "country": "South Africa",
73
+ "CN": "ZAF",
74
+ "city": "Cape Town",
75
+ "coordinates": {"lat": -33.92584, "lng": 18.42322},
76
+ "region": "South",
77
+ "address": "CSIR Campus, 15 Lower Hope Street, Rosebank, Cape Town"
78
+
79
+ },
80
+ "type": "National HPC",
81
+ "status": "Live",
82
+ "capacity": {
83
+ "GPU_type": "V100",
84
+ "n_GPUs": 36,
85
+ "pflops_performance": 1.029
86
+ },
87
+ "contact_info": {
88
+ "website": "https://www.chpc.ac.za/"
89
+ },
90
+ "last_update": "2016"
91
+ },
92
+ {
93
+ "name": "DGX A100",
94
+ "location": {
95
+ "country": "Tunisia",
96
+ "city": "Tunis",
97
+ "CN": "TUN",
98
+ "coordinates": {"lat": 36.89913191678015, "lng": 10.18927862098627},
99
+ "region": "North",
100
+ "address": "ESPRIT School of Business, Campus ESB Lot N掳46, Z.I Chotrana II, 2088, Ariana"
101
+
102
+ },
103
+ "type": "Private Workstation",
104
+ "status": "Live",
105
+ "capacity": {
106
+ "GPU_type": "A100",
107
+ "n_GPUs": 8,
108
+ "pflops_performance": 5
109
+ },
110
+ "contact_info": {
111
+ "website": "https://www.esb.tn/en"
112
+ },
113
+ "last_update": "2024"
114
+ }
115
+ ]
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ dash
2
+ plotly
3
+ pandas
4
+ uvicorn
5
+ huggingface_hub
utils.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Flatten the JSON data
2
+ def flatten_json(y):
3
+ out = {}
4
+
5
+ def flatten(x, name=''):
6
+ if type(x) is dict:
7
+ for a in x:
8
+ flatten(x[a], f"{name}{a}_")
9
+ elif type(x) is list:
10
+ for i, a in enumerate(x):
11
+ flatten(a, f"{name}{i}_")
12
+ else:
13
+ out[name[:-1]] = x
14
+
15
+ flatten(y)
16
+ return out