Skip to content

Commit eab9c50

Browse files
authored
Create docs for program & program execution (#722)
1 parent c10aa35 commit eab9c50

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Programs
2+
3+
## Overview
4+
5+
Program is a class that let users define expressions on vector elements, and have ICICLE compile it for the backends for a fused implementation. This solves memory bottlenecks and also let users customize algorithms such as sumcheck. Program can create only element-wise lambda functions.
6+
7+
8+
## C++ API
9+
10+
### Symbol
11+
12+
Symbol is the basic (template) class that allow users to define their own program. The lambda function the user define will operate on symbols.
13+
14+
### Defining lambda function
15+
16+
To define a custom lambda function the user will use Symbol:
17+
```cpp
18+
void lambda_multi_result(std::vector<Symbol<scalar_t>>& vars)
19+
{
20+
const Symbol<scalar_t>& A = vars[0];
21+
const Symbol<scalar_t>& B = vars[1];
22+
const Symbol<scalar_t>& C = vars[2];
23+
const Symbol<scalar_t>& EQ = vars[3];
24+
vars[4] = EQ * (A * B - C) + scalar_t::from(9);
25+
vars[5] = A * B - C.inverse();
26+
vars[6] = vars[5];
27+
vars[3] = 2 * (var[0] + var[1]) // all variables can be both inputs and outputs
28+
}
29+
```
30+
31+
Each symbol element at the vector argument `var` represent an input or an output. The type of the symbol (`scalar_t` in this example) will be the type of the inputs and outputs. In this example we created a lambda function with four inputs and three outputs.
32+
33+
In this example there are four input variables and three three outputs. Inside the function the user can define custom expressions on them.
34+
35+
Program support few pre-defined programs. The user can use those pre-defined programs without creating a lambda function, as will be explained in the next section.
36+
37+
### Creating program
38+
39+
To execute the lambda function we just created we need to create a program from it.
40+
To create program from lambda function we can use the following constructor:
41+
42+
```cpp
43+
Program(std::function<void(std::vector<Symbol<S>>&)> program_func, const int nof_parameters)
44+
```
45+
46+
`program_func` is the lambda function (in the example above `lambda_multi_result`) and `nof_parameters` is the total number of parameter (inputs + outputs) for the lambda (seven in the above example).
47+
48+
#### Pre-defined programs
49+
50+
As mentioned before, there are few pre-defined programs the user can use without the need to create a lambda function first. The enum `PreDefinedPrograms` contains the pre-defined program. Using pre-defined function will lead to better performance compared to creating the equivalent lambda function.
51+
To create a pre-defined program a different constructor is bing used:
52+
53+
```cpp
54+
Program(PreDefinedPrograms pre_def)
55+
```
56+
57+
`pre_def` is the pre-defined program (from `PreDefinedPrograms`).
58+
59+
##### PreDefinedPrograms
60+
61+
```cpp
62+
enum PreDefinedPrograms {
63+
AB_MINUS_C = 0,
64+
EQ_X_AB_MINUS_C
65+
};
66+
```
67+
68+
`AB_MINUS_C` - the pre-defined program `AB - C` for the input vectors `A`, `B` and `C`
69+
70+
`EQ_X_AB_MINUS_C` - the pre-defined program `EQ(AB - C)` for the input vectors `A`, `B`, `C` and `EQ`
71+
72+
73+
### Executing program
74+
75+
To execute the program the `execute_program` function from the vector operation API should be used. This operation is supported by the CPU and CUDA backends.
76+
77+
78+
```cpp
79+
template <typename T>
80+
eIcicleError
81+
execute_program(std::vector<T*>& data, const Program<T>& program, uint64_t size, const VecOpsConfig& config);
82+
```
83+
84+
The `data` vector is a vector of pointers to the inputs and output vectors, `program` is the program to execute, `size` is the length of the vectors and `config` is the configuration of the operation.
85+
86+
For the configuration the field `is_a_on_device` determined whethere the data (*inputs and outputs*) is on device or not. After the execution `data` will reside in the same place as it did before (i.e. the field `is_result_on_device` is irrelevant.)
87+
88+
> **_NOTE:_** Using program for executing lambdas is recommended only while using the CUDA backend. Program's primary use is to let users to customize algorithms (such as sumcheck).

docs/docs/icicle/primitives/vec_ops.md

+15
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ template <typename T>
7878
eIcicleError vector_div(const T* vec_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output);
7979
```
8080

81+
#### `execute_program`
82+
83+
Execute a user-defined lambda function with arbitrary number of input and output variables.
84+
85+
```cpp
86+
template <typename T>
87+
eIcicleError
88+
execute_program(std::vector<T*>& data, const Program<T>& program, uint64_t size, const VecOpsConfig& config);
89+
```
90+
91+
`is_result_on_device` of VecOpsConfig is not used here.
92+
93+
For more details see [program](./program.md).
94+
8195
#### `vector_accumulate`
8296
8397
Adds vector b to a, inplace.
@@ -208,6 +222,7 @@ template <typename T>
208222
eIcicleError polynomial_division(const T* numerator, int64_t numerator_deg, const T* denumerator, int64_t denumerator_deg, const VecOpsConfig& config, T* q_out /*OUT*/, uint64_t q_size, T* r_out /*OUT*/, uint64_t r_size);
209223
```
210224

225+
211226
### Rust and Go bindings
212227

213228
- [Golang](../golang-bindings/vec-ops.md)

docs/sidebars.ts

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ const cppApi = [
6666
label: "Vector operations",
6767
id: "icicle/primitives/vec_ops",
6868
},
69+
{
70+
type: "doc",
71+
label: "Program",
72+
id: "icicle/primitives/program",
73+
},
6974
{
7075
type: "doc",
7176
label: "Polynomials",

0 commit comments

Comments
 (0)