Running Source Code Tasks
Learn how to run programmatically single-source applications on the Signaloid Cloud Compute Engine
You can run a single-source application on the Signaloid Cloud Compute Engine via an API request. The example single-source C application below calculates how uncertainties in empirical model parameters affect the uncertainty distribution of the model's output, for a model of a physical process. The original source code lives in Brown-Ham model example. This code calculates the output of the model and prints the result to the standard output.
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <uxhw.h>
static void
loadInputs(double * G, double * M, double * Rs, double * b, double * gamma, double * phi)
{
double empiricalTaylorFactorValues[] = {
3.2, 3.9, 4.1, 3.2, 3.8, 3.8, 2.1, 3.0, 1.9, 3.9,
2.3, 2.2, 3.2, 2.2, 3.9, 2.2, 1.9, 3.2, 3.9, 3.1,
};
*M = UxHwDoubleDistFromSamples(empiricalTaylorFactorValues, sizeof(empiricalTaylorFactorValues)/sizeof(double));
*G = UxHwDoubleUniformDist(6E10, 8E10);
*Rs = UxHwDoubleMixture(UxHwDoubleGaussDist(1E-8, 2E-9), UxHwDoubleGaussDist(3E-8, 2E-9), 0.5);
*b = 2.54E-10;
*gamma = UxHwDoubleUniformDist(0.15, 0.25);
*phi = UxHwDoubleUniformDist(0.3, 0.45);
}
int
main(int argc, char * argv[])
{
double G, M, Rs, b, gamma, phi, sigmaCMpa;
loadInputs(&G, &M, &Rs, &b, &gamma, &phi);
sigmaCMpa = ((M*gamma)/(2.0*b))*(sqrt((8.0*gamma*phi*Rs)/(M_PI*G*pow(b, 2))) - phi)/1000000;
printf("Alloy strength (σc)\t\t= %.1E MPa\n", sigmaCMpa);
return 0;
}
Prerequisites
To run a source code task via the API, you will need to have the following:
- An API key to access the Signaloid Cloud API. Please refer to Authentication for more details.
Set up the task request
The Source Code task request object has the following schema:
- TypeScript
type TraceVariable = {
File: string;
LineNumber: number;
Expression: string;
}
type SourceCodeTaskRequest = {
Type: "SourceCode";
SourceCode: {
Object: "SourceCode";
Code: string;
Arguments: string;
Language: "C" | "C++";
};
Overrides?: {
Core?: string;
TraceVariables?: TraceVariable[];
};
};
Define your source code as a string
Correctly Escaping Strings for special characters: Ensure that the Code
field of the task request object is a valid JSON string. This might require you to make sure special characters are escaped properly. Refer to the documentation for your host language for details on how to escape special characters in strings.
- TypeScript
- cURL
Escaping special characters in JavaScript: In this application we have chosen to manually escape the \n
characters as \\n
in the C code. This will allow the printf
statement to correctly receive the \n
character instructing it to print a new line as intended. An alternative approach would have been to define the source code as a raw JavaScript string and use JSON.stringify to escape the string.
const applicationCode = `#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <uxhw.h>
static void
loadInputs(double * G, double * M, double * Rs, double * b, double * gamma, double * phi)
{
double empiricalTaylorFactorValues[] = {
3.2, 3.9, 4.1, 3.2, 3.8, 3.8, 2.1, 3.0, 1.9, 3.9,
2.3, 2.2, 3.2, 2.2, 3.9, 2.2, 1.9, 3.2, 3.9, 3.1,
};
*M = UxHwDoubleDistFromSamples(empiricalTaylorFactorValues, sizeof(empiricalTaylorFactorValues)/sizeof(double));
*G = UxHwDoubleUniformDist(6E10, 8E10);
*Rs = UxHwDoubleMixture(UxHwDoubleGaussDist(1E-8, 2E-9), UxHwDoubleGaussDist(3E-8, 2E-9), 0.5);
*b = 2.54E-10;
*gamma = UxHwDoubleUniformDist(0.15, 0.25);
*phi = UxHwDoubleUniformDist(0.3, 0.45);
}
int
main(int argc, char * argv[])
{
double G, M, Rs, b, gamma, phi, sigmaCMpa;
loadInputs(&G, &M, &Rs, &b, &gamma, &phi);
sigmaCMpa = ((M*gamma)/(2.0*b))*(sqrt((8.0*gamma*phi*Rs)/(M_PI*G*pow(b, 2))) - phi)/1000000;
printf("Alloy strength (σc)\\t\\t= %.1E MPa\\n", sigmaCMpa);
return 0;
}`;
Escaping special characters in Bash shell: In this application we have chosen to manually escape the \n
characters as \\n
in the C code. This will allow the printf
statement to correctly receive the \n
character instructing it to print a new line as intended.
# Source code copied from src/v3 of https://github.com/signaloid/Signaloid-Demo-Metallurgy-BrownHamModel
taskSourceCode='
#include <math.h>\n
#include <stdint.h>\n
#include <stdio.h>\n
#include <uxhw.h>\n\n
static void\n
loadInputs(double *G, double *M, double *Rs, double *b, double *gamma, double *phi)\n
{\n
double empiricalTaylorFactorValues[] = {\n
3.2, 3.9, 4.1, 3.2, 3.8, 3.8, 2.1, 3.0, 1.9, 3.9,\n
2.3, 2.2, 3.2, 2.2, 3.9, 2.2, 1.9, 3.2, 3.9, 3.1,\n
};\n\n
*M = UxHwDoubleDistFromSamples(empiricalTaylorFactorValues, sizeof(empiricalTaylorFactorValues)/sizeof(double));\n
*G = UxHwDoubleUniformDist(6E10, 8E10);\n
*Rs = UxHwDoubleMixture(UxHwDoubleGaussDist(1E-8, 2E-9), UxHwDoubleGaussDist(3E-8, 2E-9), 0.5);\n
*b = 2.54E-10;\n
*gamma = UxHwDoubleUniformDist(0.15, 0.25);\n
*phi = UxHwDoubleUniformDist(0.3, 0.45);\n
}\n\n
int\n
main(int argc, char *argv[])\n
{\n
double G, M, Rs, b, gamma, phi, sigmaCMpa;\n\n
loadInputs(&G, &M, &Rs, &b, &gamma, &phi);\n\n
sigmaCMpa = ((M*gamma)/(2.0*b))*(sqrt((8.0*gamma*phi*Rs)/(M_PI*G*pow(b, 2))) - phi)/1000000;\n\n
printf(\"Alloy strength (σc)\\t\\t= %.1E MPa\\n\", sigmaCMpa);\n\n
return 0;\n
}
'
Task request object for an uncertainty-tracking (UT) C0 or C0 Pro core
You can use the Code
field to specify the source code of your application as a string. The Language
field specifies the programming language of the source code. The Arguments
field specifies the command line arguments to be passed to the application when it is executed. You can override the Core
field to choose one of the default Signaloid cores or one of your custom Signaloid cores that you want your application to run on. The Core
field is optional and if you omit it, your task will run on the C0-XS+
core.
- TypeScript
- cURL
// Core ID of the C0-S+ core
const coreID = "cor_b21e4de9927158c1a5b603c2affb8a09";
const taskRequest = {
Type: "SourceCode",
SourceCode: {
Object: "SourceCode",
Code: applicationCode,
Arguments: "",
Language: "C",
},
Overrides: {
Core: coreID,
},
};
# Core ID of the C0-S+ core
signaloidCoreId="cor_b21e4de9927158c1a5b603c2affb8a09"
taskObject='{
"Type": "SourceCode",
"SourceCode": {
"Object": "SourceCode",
"Code": "'$(echo $taskSourceCode)'",
"Arguments": "",
"Language": "C"
},
"Overrides": {
"Core": "'$signaloidCoreId'"
}
}'
Task request object for a C0 or C0 Pro Reference core
When running an application on the Reference microarchitecture on C0 or C0 Pro, the Signaloid Cloud Compute Engine needs to know which variables of your source code to trace. To show distributional output at the end of execution, the Signaloid Cloud Compute Engine needs to accumulate the particle values of variables across the different re-executions of the application. The traced variables can be of double
or float
base type, including typedef
definitions to these types. See here for more details about what kinds of expressions you can trace.
Use the TraceVariables
element in Overrides
of the task request object to instruct the Signaloid Cloud Compute Engine about the variables to trace. Your source code may contain multiple variables with the same name, defined in different scopes of your source code. Because of this, the Signaloid Cloud Developer Platform needs to know the file and line number of the declaration of the variable that you wish to trace to be able to uniquely identify it.
The following code snippets show how to use the Signaloid API calls to instruct the Signaloid Cloud Compute Engine to run on C0 Reference core the source code shown at the top of the page. The TraceVariables
element of the Task object, instructs the Signaloid Cloud Compute Engine to trace variable sigmaCMpa
, in line 25 of file main.c
. By convention, the file name of source code task in Signaloid Cloud Compute Engine is always main.c
.
- TypeScript
- cURL
Escaping special characters in JavaScript: In this application we have chosen to manually escape the \n
characters as \\n
in the C code. This will allow the printf
statement to correctly receive the \n
character instructing it to print a new line as intended. An alternative approach would have been to define the source code as a raw JavaScript string and use JSON.stringify to escape the string.
// Core ID of the C0-Reference core
const coreID = "cor_9a3efb0094405df5aeb61cf1f29606a0";
const taskRequest = {
Type: "SourceCode",
SourceCode: {
Object: "SourceCode",
Code: applicationCode,
Arguments: "",
Language: "C",
},
Overrides: {
Core: coreID,
TraceVariables: [{ Expression: "sigmaCMpa", File: "main.c", LineNumber: 25 }]
},
};
Escaping special characters in Bash shell: In this application we have chosen to manually escape the \n
characters as \\n
in the C code. This will allow the printf
statement to correctly receive the \n
character instructing it to print a new line as intended.
# Core ID of the C0-Reference core
signaloidCoreId="cor_9a3efb0094405df5aeb61cf1f29606a0"
taskObject='{
"Type": "SourceCode",
"SourceCode": {
"Object": "SourceCode",
"Code": "'$(echo $taskSourceCode)'",
"Arguments": "",
"Language": "C"
},
"Overrides": {
"Core": "'$signaloidCoreId'",
"TraceVariables": [{"Expression":"sigmaCMpa","File":"main.c","LineNumber":25}]
}
}'
Submit the task to the API
- TypeScript
- cURL
Submit the task request to the API via a POST
request to /tasks
. The code snippet below shows how to submit the task request to the API using the axios
library.
// API token generated from signaloid.io/settings/api
const apiToken = "scce_yourSignaloidCloudApiKey";
// Setup HTTP client
const axios = require("axios");
const signaloidClient = axios.create({
baseURL: "https://api.signaloid.io",
});
// Setup request headers
signaloidClient.defaults.headers["Authorization"] = `${apiToken}`;
signaloidClient.defaults.headers["Content-Type"] = "application/json";
console.log("Submitting the task to the API...");
let taskPostResponse;
try {
taskPostResponse = await signaloidClient.post("/tasks", taskRequest);
if (taskPostResponse.data.TaskID) {
console.log(`...task successfully created with ID: ${taskPostResponse.data.TaskID}`);
}
} catch (error) {
console.log("Error:", error);
}
If the task is valid, and the API has accepted the request, the taskPostResponse
variable will contain information about the task. The code snippet below shows the contents of the taskPostResponse
variable after the task has been successfully created.
{
"data": {
"Object": "Task",
"TaskID": "tsk_6dcae4d1c4f585901efa12a89a063996",
"Owner": "usr_yourSignaloidCloudUserID",
"Application": {...}, // The application that was submitted to the API
"Status": "Accepted",
[...other response keys omitted]
},
"status": 202,
"statusText": "Accepted",
[...other response keys omitted]
}
You can now use the TaskID
to retrieve the status and outputs of the task from the API.
Submit the task request to the API via a POST
request to /tasks
. The code snippet below shows how to submit the task request to the API using curl
.
# API token generated from signaloid.io/settings/api
signaloidAPIKey="scce_yourSignaloidCloudApiKey"
taskEndpointResponse=$(curl -s --request POST --location 'https://api.signaloid.io/tasks' \
--header "Content-Type: application/json" \
--header "Authorization: $signaloidAPIKey" \
--data "$taskObject")
If the task is valid, and the API has accepted the request, the taskEndpointResponse
variable will contain information about the task. The code snippet below shows the contents of the taskEndpointResponse
variable after the task has been successfully created.
{
"data": {
"Object": "Task",
"TaskID": "tsk_6dcae4d1c4f585901efa12a89a063996",
"Owner": "usr_yourSignaloidCloudUserID",
"Application": {...}, // The application that was submitted to the API
"Status": "Accepted",
[...other response keys omitted]
},
"status": 202,
"statusText": "Accepted",
[...other response keys omitted]
}
The TaskID
will allow you to retrieve the status and outputs of the task from the API.