Introduction

Placeholder.

Step #1 - Identify your app's sparse matrix-related main bottleneck

graph TB subgraph Application ["Your Application"] direction TB A["func_a()"] B["func_b()"] C["func_heavy()"] D["func_c()"] E["func_d()"] %% Force vertical order using invisible links A ~~~ B B ~~~ C C ~~~ D D ~~~ E end %% Red highlight for the bottleneck inside the application style C stroke:#cc0000,stroke-width:4px;
#include <stdio.h>

// Forward declarations
void func_a(void);
void func_b(void);
void func_heavy(void);
void func_c(void);
void func_d(void);

int main(void) {
    func_a();
    func_b();
    func_heavy(); // WARNING: Performance Bottleneck
    func_c();
    func_d();
    return 0;
}

Step #2 - Install the Sparsr SDK

Contact us.

Step #3 - Write your Sparsr Kernel

Isolate your bottlenecked sparse operation into a Sparser kernel. This is done by converting your bottlenecked CPU-bound code into a Sparsr Kernel, a new application written in Sparsr Assembly or in C language (with assembly embeddings) that will be executed on Sparsr. Your main application (the Host App) remains mostly untouched, but when the previously-bottlenecked code is reached, the execution jumps to Sparsr, and then returns to your application.

graph LR subgraph CPU ["CPU"] subgraph Application ["Your Application"] direction TB A["func_a()"] B["func_b()"] C["func_heavy()"] D["func_c()"] E["func_d()"] %% Force vertical order using invisible links A ~~~ B B ~~~ C C ~~~ D D ~~~ E end end subgraph Sparsr ["Sparsr"] %% Placeholder for Sparsr content Backend["Your Kernel"] end %% Arrows connecting the heavy function and the backend kernel C --> Backend Backend --> C %% Red highlight for the bottleneck inside the application style C stroke:#cc0000,stroke-width:4px;
#include <stdio.h>
#include <stdbool.h>
#include "sparsr_emu.h"

// Configuration constant to toggle the Sparsr accelerator
#define SPARSR_ENABLED true

// Forward declarations
void func_a(void);
void func_b(void);
void func_heavy(void);
void func_heavy_on_sparsr(void);
void func_c(void);
void func_d(void);

// Stubbed compressed sparse matrix data and kernel definition
const char* my_kernel = "csr_matrix_vector_multiply";
int stub_sparse_matrix_data[] = {1, 0, 4, 0, 0, 9, 3, 0};

int main(void) {
    sparsr_init();

    func_a();
    func_b();

    #if SPARSR_ENABLED
    func_heavy_on_sparsr();
    #else
    func_heavy(); // WARNING: Performance Bottleneck
    #endif

    func_c();
    func_d();

    sparsr_stop_kernel();

    return 0;
}

// Accelerated function utilizing the Sparsr emulator API. This code runs as part of your Host App on CPU, and its main purpose is to transfer data between your Host App and Sparsr and handle the execution of your optimized algorithm on Sparsr.
void func_heavy_on_sparsr(void) {
    load_kernel("my_kernel.spas");
    sparsr_load_data(stub_sparse_matrix_data);
    sparsr_run_kernel();
    sparsr_read_data();
}
# File: my_kernel.spas
# Your Kernel, written in Sparsr Assembly Language, running on Sparsr.
LW $t1,1($zero)
LW $t2,2($zero)
ADD $t3,$t1,$t2
AND $t4,$t1,$t2
XOR $t5,$t1,$t2
OR $t6,$t1,$t2
SW $t3,3($zero)
SW $t4,4($zero)
SW $t5,5($zero)
SW $t6,6($zero)

Step #4 - Test the functionality on the Sparsr Emulator

exe/host_app.exe: host_app.c sparsr_emu.h sparsr_emu.a
    gcc -o "$@" "$<" -L. sparsr_emu.a -lstdc++ -lOpenCL -pthread

Run make, then execute host_app.exe. Your application will run fully on CPU (without FPGAs nor custom hardware). Your Sparsr Kernel will run on CPU, on a Sparsr emulator, at a very low speed. Use this to test your application functionality, not for production performance.

Step #5 - Run your entire application using Sparsr

TBD.