The MLIR dialect, its conversion passes (TFHEToConcrete, ConcreteToCAPI, ConcreteToLLVM), the optimizer component, the compiler binary, the Rust crate and the program_info parameter file all still carried the upstream project's name. They now carry this one's. Two things deliberately keep the word, because in them it is not the name. mlir::OpTrait CRTP parameters mean "the derived type", so they are spelled Derived and OpTy — LLVM's other conventional spelling for the same idiom. concreteShape is a capnp field: renaming it would change the serialized protocol, and the prose describing it is ordinary English. This also repairs references the earlier partial rename left dangling: Security.cpp included concrete/curves.gen.h and the directory is torus/, torus-cpu.h included concrete-num_complex.h, the Torus dialect CMakeLists named ConcreteOps.td, and compiler/setup.py asked find_namespace_packages for a "concrete" package that no longer exists — so it built without the package it ships.
9.7 KiB
Debug
This document provides guidance on debugging the compilation process.
Compiler debug and verbose modes
Two configuration options are available to help you understand the compilation process:
- compiler_verbose_mode: Prints the compiler passes and shows the transformations applied. It can help identify the crash location if a crash occurs.
- compiler_debug_mode: A more detailed version of the verbose mode, providing additional information, particularly useful for diagnosing crashes.
{% hint style="warning" %}
These flags might not work as expected in Jupyter notebooks as they output to stderr directly from C++.
{% endhint %}
Debug artifacts
Torus includes an artifact system that simplifies the debugging process by automatically or manually exporting detailed information during compilation failures.
Automatic export
When a compilation fails, artifacts are automatically exported to the .artifacts directory in the working directory. Here's an example of what gets exported when a function fails to compile:
def f(x):
return np.sin(x)
This function fails to compile because Torus does not support floating-point outputs. When you try to compile it, an exception will be raised and the artifacts will be exported automatically. The following files will be generated in the .artifacts directory:
environment.txt: Information about your system setup, including the operating system and Python version.
Linux-5.12.13-arch1-2-x86_64-with-glibc2.29 #1 SMP PREEMPT Fri, 25 Jun 2021 22:56:51 +0000
Python 3.8.10
requirements.txt: The installed Python packages and their versions.
astroid==2.15.0
attrs==22.2.0
auditwheel==5.3.0
...
wheel==0.40.0
wrapt==1.15.0
zipp==3.15.0
function.txt: The code of the function that failed to compile.
def f(x):
return np.sin(x)
parameters.txt: Information about the encryption status function's parameters.
x :: encrypted
1.initial.graph.txt: The textual representation of the initial computation graph right after tracing.
%0 = x # EncryptedScalar<uint3>
%1 = sin(%0) # EncryptedScalar<float64>
return %1
final.graph.txt: The textual representation of the final computation graph right before MLIR conversion.
%0 = x # EncryptedScalar<uint3>
%1 = sin(%0) # EncryptedScalar<float64>
return %1
traceback.txt: Details of the error occurred.
Traceback (most recent call last):
File "/path/to/your/script.py", line 9, in <module>
circuit = f.compile(inputset)
File "/usr/local/lib/python3.10/site-packages/torus/fhe/compilation/decorators.py", line 159, in compile
return self.compiler.compile(inputset, configuration, artifacts, **kwargs)
File "/usr/local/lib/python3.10/site-packages/torus/fhe/compilation/compiler.py", line 437, in compile
mlir = GraphConverter.convert(self.graph)
File "/usr/local/lib/python3.10/site-packages/torus/fhe/mlir/graph_converter.py", line 677, in convert
GraphConverter._check_graph_convertibility(graph)
File "/usr/local/lib/python3.10/site-packages/torus/fhe/mlir/graph_converter.py", line 240, in _check_graph_convertibility
raise RuntimeError(message)
RuntimeError: Function you are trying to compile cannot be converted to MLIR
%0 = x # EncryptedScalar<uint3> ∈ [3, 5]
%1 = sin(%0) # EncryptedScalar<float64> ∈ [-0.958924, 0.14112]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ only integer operations are supported
/path/to/your/script.py:6
return %1
Manual exports
Manual exports are mostly used for visualization and demonstrations. Here is how to perform one:
from torus import fhe
import numpy as np
artifacts = fhe.DebugArtifacts("/tmp/custom/export/path")
@fhe.compiler({"x": "encrypted"})
def f(x):
return 127 - (50 * (np.sin(x) + 1)).astype(np.int64)
inputset = range(2 ** 3)
circuit = f.compile(inputset, artifacts=artifacts)
artifacts.export()
After running the code, you will find the following files under /tmp/custom/export/path directory:
1.initial.graph.txt: The textual representation of the initial computation graph right after tracing.
%0 = x # EncryptedScalar<uint1>
%1 = sin(%0) # EncryptedScalar<float64>
%2 = 1 # ClearScalar<uint1>
%3 = add(%1, %2) # EncryptedScalar<float64>
%4 = 50 # ClearScalar<uint6>
%5 = multiply(%4, %3) # EncryptedScalar<float64>
%6 = astype(%5, dtype=int_) # EncryptedScalar<uint1>
%7 = 127 # ClearScalar<uint7>
%8 = subtract(%7, %6) # EncryptedScalar<uint1>
return %8
2.after-fusing.graph.txt: The textual representation of the intermediate computation graph after fusing.
%0 = x # EncryptedScalar<uint1>
%1 = subgraph(%0) # EncryptedScalar<uint1>
%2 = 127 # ClearScalar<uint7>
%3 = subtract(%2, %1) # EncryptedScalar<uint1>
return %3
Subgraphs:
%1 = subgraph(%0):
%0 = input # EncryptedScalar<uint1>
%1 = sin(%0) # EncryptedScalar<float64>
%2 = 1 # ClearScalar<uint1>
%3 = add(%1, %2) # EncryptedScalar<float64>
%4 = 50 # ClearScalar<uint6>
%5 = multiply(%4, %3) # EncryptedScalar<float64>
%6 = astype(%5, dtype=int_) # EncryptedScalar<uint1>
return %6
3.final.graph.txt: The textual representation of the final computation graph right before MLIR conversion.
%0 = x # EncryptedScalar<uint3> ∈ [0, 7]
%1 = subgraph(%0) # EncryptedScalar<uint7> ∈ [2, 95]
%2 = 127 # ClearScalar<uint7> ∈ [127, 127]
%3 = subtract(%2, %1) # EncryptedScalar<uint7> ∈ [32, 125]
return %3
Subgraphs:
%1 = subgraph(%0):
%0 = input # EncryptedScalar<uint1>
%1 = sin(%0) # EncryptedScalar<float64>
%2 = 1 # ClearScalar<uint1>
%3 = add(%1, %2) # EncryptedScalar<float64>
%4 = 50 # ClearScalar<uint6>
%5 = multiply(%4, %3) # EncryptedScalar<float64>
%6 = astype(%5, dtype=int_) # EncryptedScalar<uint1>
return %6
mlir.txt: Information about the MLIR of the function which was compiled using the provided input-set.
module {
func.func @main(%arg0: !FHE.eint<7>) -> !FHE.eint<7> {
%c127_i8 = arith.constant 127 : i8
%cst = arith.constant dense<"..."> : tensor<128xi64>
%0 = "FHE.apply_lookup_table"(%arg0, %cst) : (!FHE.eint<7>, tensor<128xi64>) -> !FHE.eint<7>
%1 = "FHE.sub_int_eint"(%c127_i8, %0) : (i8, !FHE.eint<7>) -> !FHE.eint<7>
return %1 : !FHE.eint<7>
}
}
client\_parameters.json: Information about the client parameters chosen by Torus.
{
"bootstrapKeys": [
{
"baseLog": 22,
"glweDimension": 1,
"inputLweDimension": 908,
"inputSecretKeyID": 1,
"level": 1,
"outputSecretKeyID": 0,
"polynomialSize": 8192,
"variance": 4.70197740328915e-38
}
],
"functionName": "main",
"inputs": [
{
"encryption": {
"encoding": {
"isSigned": false,
"precision": 7
},
"secretKeyID": 0,
"variance": 4.70197740328915e-38
},
"shape": {
"dimensions": [],
"sign": false,
"size": 0,
"width": 7
}
}
],
"keyswitchKeys": [
{
"baseLog": 3,
"inputSecretKeyID": 0,
"level": 6,
"outputSecretKeyID": 1,
"variance": 1.7944329123150665e-13
}
],
"outputs": [
{
"encryption": {
"encoding": {
"isSigned": false,
"precision": 7
},
"secretKeyID": 0,
"variance": 4.70197740328915e-38
},
"shape": {
"dimensions": [],
"sign": false,
"size": 0,
"width": 7
}
}
],
"packingKeyswitchKeys": [],
"secretKeys": [
{
"dimension": 8192
},
{
"dimension": 908
}
]
}
Asking the community
You can seek help with your issue by asking a question directly in the community forum.
Submitting an issue
If you cannot find a solution in the community forum, or if you have found a bug in the library, you could create an issue in our GitHub repository.
For bug reports, try to:
- Avoid randomness to ensure reproducibility of the bug
- Minimize your function while keeping the bug to expedite the fix
- Include your input-set in the issue
- Provide clear reproduction steps
- Include debug artifacts in the issue
For feature requests, try to:
- Give a minimal example of the desired behavior
- Explain your use case