Skip to content

Commit

Permalink
Merge pull request #3 from nhatdongdang/feature/final-working-program
Browse files Browse the repository at this point in the history
Make base program compatible with speed_cpu.sh and add CI workflow
  • Loading branch information
rozukke authored Jun 25, 2024
2 parents 4ec6297 + 20ebfc2 commit fc3d74f
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 91 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
push:
branches: main
paths: ['**.cu','**.c','**.cpp', '**.h', '**CMakeLists.txt']
pull_request:
branches: main
paths: ['**.cu','**.c','**.cpp', '**.h', '**CMakeLists.txt']

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install pandas
- name: Build project
run: |
make build
- name: Run test suite
run: |
make test
33 changes: 33 additions & 0 deletions .github/workflows/cpp-linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: cpp-linter
on:
pull_request:
branches: main
paths: ['**.cu','**.cpp','**.c', '**.h', '**CMakeLists.txt']
push:
branches: main
paths: ['**.cu','**.cpp','**.c', '**.h', '**CMakeLists.txt']

permissions:
contents: write
pull-requests: write
actions: write

jobs:
cpp-linter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cpp-linter/cpp-linter-action@v2
id: linter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
style: 'file' # Use .clang-format config file.
tidy-checks: '-*' # disable clang-tidy checks.
version: 17
thread-comments: true
format-review: true

- name: Run clang-format
if: steps.linter.outputs.clang-format-checks-failed > 0
run: exit 1
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@
*.exe
*.out
*.app

# misc
.vscode
build
results.csv
15 changes: 13 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)

# Set the project name
project(ichida-algo)
Expand All @@ -7,4 +7,15 @@ set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED True)

add_executable(speed_cpu src/main.c)
set(SRC_DIR src)
set(INC_DIR include)

# Source files
file(GLOB_RECURSE SOURCE_FILES ${SRC_DIR}/*.c)

include_directories(include)
add_executable(speed_cpu ${SOURCE_FILES})
target_link_libraries(speed_cpu m)



24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

.PHONY: all test clean run build run_test

clean:
rm -rf build
rm speed_cpu

build:
cmake -Bbuild
$(MAKE) -C ./build
mv ./build/speed_cpu ./

run: build
./speed_demo_cpu.sh ./weights_and_biases.txt ./tensors

run_test: build
./speed_cpu ./weights_and_biases.txt ./tensors

test: build
./speed_demo_cpu.sh ./weights_and_biases.txt ./tensors
mv ./results.csv ./test
python3 ./test/verify_csv.py


17 changes: 17 additions & 0 deletions include/matrix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

typedef struct {
int rows;
int cols;
float** data;
} matrix;

matrix* createMatrix(int rows, int cols);

void multiplyMatrices(const matrix* a, const matrix* b, const matrix* result);

void addMatrix(matrix* a, const matrix* b);

void ReLU(matrix* a);

void softmax(matrix* a);
5 changes: 5 additions & 0 deletions include/util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

char letters[52] = {'A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i',
'J', 'j', 'K', 'k', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r',
'S', 's', 'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'Y', 'y', 'Z', 'z'};
Empty file modified speed_demo_cpu.sh
100644 → 100755
Empty file.
144 changes: 55 additions & 89 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,71 +1,13 @@
#include <math.h>
#include "matrix.h"
#include "util.h"
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
int rows;
int cols;
float** data;
} matrix;

matrix* weight[7];
matrix* biase[7];

matrix* createMatrix(int rows, int cols) {
matrix* res = (matrix*)malloc(sizeof(matrix));
res->rows = rows;
res->cols = cols;
res->data = (float**)malloc(rows * sizeof(float*));
for (int i = 0; i < rows; i++) {
res->data[i] = (float*)malloc(cols * sizeof(float));
}
return res;
}

void multiplyMatrices(const matrix* a, const matrix* b, const matrix* result) {
for (int i = 0; i < result->rows; i++) {
for (int j = 0; j < result->cols; j++) {
float sum = 0;
for (int k = 0; k < a->cols; k++) {
sum += (a->data)[i][k] * ((b->data)[k][j]);
}
(result->data)[i][j] = sum;
}
}
}

void addMatrix(matrix* a, const matrix* b) {
for (int i = 0; i < a->rows; i++) {
for (int j = 0; j < a->cols; j++) {
(a->data)[i][j] += (b->data)[i][j];
}
}
}

void ReLU(matrix* a) {
for (int i = 0; i < a->rows; i++) {
for (int j = 0; j < a->cols; j++) {
if ((a->data)[i][j] < (float)0)
(a->data)[i][j] = (float)0;
}
}
}

void softmax(matrix* a) {
float res = (float)0;
for (int i = 0; i < a->rows; i++) {
for (int j = 0; j < a->cols; j++) {
res += exp((a->data)[i][j]);
}
}
for (int i = 0; i < a->rows; i++) {
for (int j = 0; j < a->cols; j++) {
(a->data)[i][j] /= res;
}
}
}

void processWeight(char* line, int layer) {
char* token;
float value;
Expand Down Expand Up @@ -95,8 +37,8 @@ void processBiase(char* line, int layer) {
}
}

void readModel() {
FILE* file = fopen("../weights_and_biases.txt", "r");
void readModel(const char* fileName) {
FILE* file = fopen(fileName, "r");

char* line = NULL;
size_t len = 0;
Expand All @@ -117,9 +59,8 @@ void readModel() {
fclose(file);
}

void readInput(matrix* a, char* fileName) {
void readInput(matrix* a, const char* fileName) {
FILE* file = fopen(fileName, "r");

char* line = NULL;
size_t len = 0;
ssize_t read;
Expand All @@ -145,9 +86,10 @@ void propagateForward(const matrix* weight, const matrix* input, matrix* nextLay
addMatrix(nextLayer, biase);
}

// Get result from output layer
int getResult(matrix* a) {
int idx = 0;
float res = INT32_MIN;
float res = (a->data)[0][0];
for (int i = 0; i < a->rows; i++) {
if (res < (a->data)[i][0]) {
res = (a->data)[i][0];
Expand Down Expand Up @@ -182,11 +124,12 @@ int inference(matrix* input) {

propagateForward(weight[6], layer[5], layer[6], biase[6]);
softmax(layer[6]);

return getResult(layer[6]);
}

int main() {

int main(int argc, char* argv[]) {
// TODO: find a way to load static weights and biases
// Load model (The memory of those code should be initialize during compile time to enchance the speed)
weight[0] = createMatrix(98, 225);
weight[1] = createMatrix(65, 98);
Expand All @@ -204,30 +147,53 @@ int main() {
biase[5] = createMatrix(40, 1);
biase[6] = createMatrix(52, 1);

readModel();
readModel(argv[1]);

char str[10];
char fileName[100];
matrix* input = createMatrix(255, 1);
// Run program
const char* directory_path = argv[2];
struct dirent* entry;
DIR* dir = opendir(directory_path);

for (int i = 1; i <= 52; i++) {
if (i < 10) {
sprintf(str, "0%d", i);
} else {
sprintf(str, "%d", i);
matrix* input = createMatrix(225, 1);

// Read and process inputs
char* fileName = (char*)malloc((100) * sizeof(char));
char* fileNumStr = (char*)malloc((100) * sizeof(char));

int fileNum;
int size = 0;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) {
size++;
}
strcpy(fileName, "../tensors/");
strcat(fileName, str);
strcat(fileName, "out.txt");

// Read txt file
readInput(input, fileName);

// Check result
if (inference(input) + 1 == i) {
printf("Test %d correct ✅\n", i);
} else {
printf("Test %d incorrect ❌\n", i);
}

int* results = (int*)malloc((size + 1) * sizeof(int));
dir = opendir(directory_path);
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) {
strcpy(fileNumStr, entry->d_name);
fileNumStr[strlen(entry->d_name) - 7] = '\0';
fileNum = atoi(entry->d_name);
strcpy(fileName, directory_path);
strcat(fileName, "/");
strcat(fileName, entry->d_name);
readInput(input, fileName);
results[fileNum] = inference(input);
}
}

free(fileName);
free(fileNumStr);
closedir(dir);

// Write to csv file
FILE* fpt;
fpt = fopen("results.csv", "w+");
fprintf(fpt, "image_number, guess\n");
for (int i = 1; i <= size; i++) {
fprintf(fpt, "%d, %c\n", i, letters[results[i]]);
}

return EXIT_SUCCESS;
}
Loading

0 comments on commit fc3d74f

Please sign in to comment.