INITIAL COMMIT
This commit is contained in:
commit
1a050d28e2
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
python/__pycache__/**/*
|
||||||
|
cpp/haverscan
|
||||||
|
cpp/haverstrtok
|
||||||
|
data_10000000_flex.json
|
14
Makefile
Normal file
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
mk_fscanf:
|
||||||
|
clang++ -g cpp/fscanf.cpp cpp/haversine.cpp -o cpp/haverscan
|
||||||
|
|
||||||
|
run_fscanf:
|
||||||
|
./cpp/haverscan
|
||||||
|
|
||||||
|
mk_strtok:
|
||||||
|
clang++ -g cpp/strtok.cpp cpp/haversine.cpp -o cpp/haverstrtok
|
||||||
|
|
||||||
|
run_strtok:
|
||||||
|
./cpp/haverstrtok
|
||||||
|
|
||||||
|
run_python_json:
|
||||||
|
python ./python/haversine_json.py
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Casey Muratori's Performance Aware Programming Course
|
||||||
|
|
||||||
|
Following along Casey's course [Performance Aware Programming](https://www.computerenhance.com/s/programming-courses/archive?sort=new)
|
104
cpp/fscanf.cpp
Normal file
104
cpp/fscanf.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "haversine.h"
|
||||||
|
#include <bits/types/FILE.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
|
#define EARTH_RADIUS_KM 6371.0
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#define ITEM_COUNT 2
|
||||||
|
#else
|
||||||
|
#define ITEM_COUNT 10000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
double x0;
|
||||||
|
double y0;
|
||||||
|
double x1;
|
||||||
|
double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
#if DEBUG
|
||||||
|
FILE *fp = fopen("/home/abdelrahman/Sources/dev/"
|
||||||
|
"performance_aware_programming/test_data.json",
|
||||||
|
"rb");
|
||||||
|
#else
|
||||||
|
FILE *fp = fopen("/home/abdelrahman/Sources/dev/"
|
||||||
|
"performance_aware_programming/data_10000000_flex.json",
|
||||||
|
"rb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Item *items = (Item *)malloc(ITEM_COUNT * sizeof(Item));
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
int read = fread(buf, 1, 256, fp);
|
||||||
|
|
||||||
|
for (int i = 1; i < read; ++i) {
|
||||||
|
if (buf[i] == '{') {
|
||||||
|
fseek(fp, i, SEEK_SET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
fscanf(fp, "{\n");
|
||||||
|
|
||||||
|
int scanned = fscanf(fp,
|
||||||
|
" \"x0\": %lf,\n \"y0\": %lf,\n "
|
||||||
|
"\"x1\": %lf,\n \"y1\": %lf\n },\n ",
|
||||||
|
&(items[index].x0), &(items[index].y0),
|
||||||
|
&(items[index].x1), &(items[index].y1));
|
||||||
|
|
||||||
|
if (scanned == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t mid_time = clock();
|
||||||
|
|
||||||
|
double sum = 0.0;
|
||||||
|
|
||||||
|
for (int i = 0; i < ITEM_COUNT; ++i) {
|
||||||
|
sum += haversine_of_degrees(items[i].x0, items[i].y0, items[i].x1,
|
||||||
|
items[i].y1, EARTH_RADIUS_KM);
|
||||||
|
}
|
||||||
|
|
||||||
|
double average = sum / ITEM_COUNT;
|
||||||
|
|
||||||
|
clock_t end_time = clock();
|
||||||
|
|
||||||
|
printf("Result: %.16f\n", average);
|
||||||
|
printf("Input = %.16f seconds\n",
|
||||||
|
(double)(mid_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Math = %.16f seconds\n",
|
||||||
|
(double)(end_time - mid_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Total = %.16f seconds\n",
|
||||||
|
(double)(end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Throughput = %.16f haversines/second\n",
|
||||||
|
ITEM_COUNT / ((double)(end_time - start_time) / CLOCKS_PER_SEC));
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
for (int i = 0; i < ITEM_COUNT; ++i) {
|
||||||
|
printf("%.16f\n%.16f\n%.16f\n%.16f\n\n", items[i].x0, items[i].y0,
|
||||||
|
items[i].x1, items[i].y1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(items);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
24
cpp/haversine.cpp
Normal file
24
cpp/haversine.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "haversine.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define PI 3.14159265358979323845
|
||||||
|
#define SQUARE(X) ((X) * (X))
|
||||||
|
|
||||||
|
double radians(double degrees);
|
||||||
|
|
||||||
|
double haversine_of_degrees(double x0, double y0, double x1, double y1,
|
||||||
|
double radius) {
|
||||||
|
double dy = radians(y1 - y0);
|
||||||
|
double dx = radians(x1 - x0);
|
||||||
|
y0 = radians(y0);
|
||||||
|
y1 = radians(y1);
|
||||||
|
|
||||||
|
double root_term =
|
||||||
|
SQUARE(sin(dy / 2.0)) + cos(y0) * cos(y1) * SQUARE(sin(dx / 2.0));
|
||||||
|
|
||||||
|
double result = 2.0 * radius * asin(sqrt(root_term));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double radians(double degrees) { return (degrees * PI) / 180.0; }
|
7
cpp/haversine.h
Normal file
7
cpp/haversine.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef HAVERSINE_H
|
||||||
|
#define HAVERSINE_H
|
||||||
|
|
||||||
|
double haversine_of_degrees(double x0, double y0, double x1, double y1,
|
||||||
|
double radius);
|
||||||
|
|
||||||
|
#endif // !HAVERSINE_H
|
116
cpp/strtok.cpp
Normal file
116
cpp/strtok.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include "haversine.h"
|
||||||
|
#include <bits/types/FILE.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
|
#define EARTH_RADIUS_KM 6371.0
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#define ITEM_COUNT 2
|
||||||
|
#else
|
||||||
|
#define ITEM_COUNT 10000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
double x0;
|
||||||
|
double y0;
|
||||||
|
double x1;
|
||||||
|
double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
#if DEBUG
|
||||||
|
FILE *fp = fopen("/home/abdelrahman/Sources/dev/"
|
||||||
|
"performance_aware_programming/test_data.json",
|
||||||
|
"rb");
|
||||||
|
#else
|
||||||
|
FILE *fp = fopen("/home/abdelrahman/Sources/dev/"
|
||||||
|
"performance_aware_programming/data_10000000_flex.json",
|
||||||
|
"rb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Item *items = (Item *)malloc(ITEM_COUNT * sizeof(Item));
|
||||||
|
int index = 0;
|
||||||
|
double *elem = nullptr;
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
|
||||||
|
long length = (long)ftell(fp);
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
char *text = (char *)malloc(length + 1);
|
||||||
|
memset(text, 0, length + 1);
|
||||||
|
|
||||||
|
fread(text, 1, length, fp);
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
const char *delim = "{}[]:,\"\n ";
|
||||||
|
|
||||||
|
char *token = strtok(text, delim);
|
||||||
|
|
||||||
|
while (token) {
|
||||||
|
if (strcmp(token, "x0") == 0) {
|
||||||
|
elem = &(items[index].x0);
|
||||||
|
} else if (strcmp(token, "y0") == 0) {
|
||||||
|
elem = &(items[index].y0);
|
||||||
|
} else if (strcmp(token, "x1") == 0) {
|
||||||
|
elem = &(items[index].x1);
|
||||||
|
} else if (strcmp(token, "y1") == 0) {
|
||||||
|
elem = &(items[index].y1);
|
||||||
|
++index;
|
||||||
|
} else {
|
||||||
|
if (elem) {
|
||||||
|
char *end = &(token[strlen(token)]);
|
||||||
|
*elem = strtod(token, &end);
|
||||||
|
elem = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
token = strtok(NULL, delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t mid_time = clock();
|
||||||
|
|
||||||
|
double sum = 0.0;
|
||||||
|
|
||||||
|
for (int i = 0; i < ITEM_COUNT; ++i) {
|
||||||
|
sum += haversine_of_degrees(items[i].x0, items[i].y0, items[i].x1,
|
||||||
|
items[i].y1, EARTH_RADIUS_KM);
|
||||||
|
}
|
||||||
|
|
||||||
|
double average = sum / ITEM_COUNT;
|
||||||
|
|
||||||
|
clock_t end_time = clock();
|
||||||
|
|
||||||
|
printf("Result: %.16f\n", average);
|
||||||
|
printf("Input = %.16f seconds\n",
|
||||||
|
(double)(mid_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Math = %.16f seconds\n",
|
||||||
|
(double)(end_time - mid_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Total = %.16f seconds\n",
|
||||||
|
(double)(end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Throughput = %.16f haversines/second\n",
|
||||||
|
ITEM_COUNT / ((double)(end_time - start_time) / CLOCKS_PER_SEC));
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
int precision = 16;
|
||||||
|
for (int i = 0; i < ITEM_COUNT; ++i) {
|
||||||
|
printf("%.*f\n%.*f\n%.*f\n%.*f\n\n", precision, items[i].x0, precision,
|
||||||
|
items[i].y0, precision, items[i].x1, precision, items[i].y1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(text);
|
||||||
|
|
||||||
|
free(items);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
14
python/haversine_algorithm.py
Normal file
14
python/haversine_algorithm.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from math import radians, sin, cos, sqrt, asin
|
||||||
|
|
||||||
|
|
||||||
|
def haversine_of_degrees(x0, y0, x1, y1, radius):
|
||||||
|
dy = radians(y1 - y0)
|
||||||
|
dx = radians(x1 - x0)
|
||||||
|
y0 = radians(y0)
|
||||||
|
y1 = radians(y1)
|
||||||
|
|
||||||
|
root_term = (sin(dy / 2) ** 2) + cos(y0) * cos(y1) * (sin(dx / 2) ** 2)
|
||||||
|
|
||||||
|
result = 2 * radius * asin(sqrt(root_term))
|
||||||
|
|
||||||
|
return result
|
40
python/haversine_json.py
Normal file
40
python/haversine_json.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Naive Python version of the code
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
from haversine_algorithm import haversine_of_degrees
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
filepath = os.path.join(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||||
|
"data_10000000_flex.json",
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(filepath, "r") as json_file:
|
||||||
|
start_time = time.time()
|
||||||
|
json_input = json.load(json_file)
|
||||||
|
mid_time = time.time()
|
||||||
|
|
||||||
|
|
||||||
|
earth_radius_km = 6371
|
||||||
|
sum = 0
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for pair in json_input["pairs"]:
|
||||||
|
sum += haversine_of_degrees(
|
||||||
|
pair["x0"], pair["y0"], pair["x1"], pair["y1"], earth_radius_km
|
||||||
|
)
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
average = sum / count
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
|
||||||
|
print(f"Result: {average}")
|
||||||
|
print(f"Input = {mid_time - start_time} seconds")
|
||||||
|
print(f"Math = {end_time - mid_time} seconds")
|
||||||
|
print(f"Total = {end_time - start_time} seconds")
|
||||||
|
print(f"Throughput = {count / (end_time - start_time)} haversines/second")
|
16
test_data.json
Normal file
16
test_data.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"pairs": [
|
||||||
|
{
|
||||||
|
"x0": -4.618412003630709,
|
||||||
|
"y0": 135.8153583196389,
|
||||||
|
"x1": -12.383220322958223,
|
||||||
|
"y1": 85.20071945064029
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x0": 47.817641963713584,
|
||||||
|
"y0": 111.40590001495877,
|
||||||
|
"x1": -34.52607922832944,
|
||||||
|
"y1": -127.52991299863771
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user