Skip to content

Commit

Permalink
Requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pschowitz committed Jan 15, 2025
1 parent a25edcc commit 3512363
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 69 deletions.
108 changes: 62 additions & 46 deletions tutorials/hsdk_rt_analysis/artifact/base.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2024 UNIVERSITY OF BRITISH COLUMBIA. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* This is a modified version of several files from the Holoscan SDK
Expand All @@ -20,9 +20,23 @@
#include <holoscan/holoscan.hpp>
#include <sys/time.h>

// Difference factor
#define ONE_SEC_TO_NS (uint64_t)1000000000

// Macro to convert seconds to nanoseconds
#define SEC_TO_NS(t) ((t) * ONE_SEC_TO_NS)

/*
* Macro to subtract two timespec structures.
* Parameters:
* - tsp: Pointer to the minuend timespec structure.
* - usp: Pointer to the subtrahend timespec structure.
* - vsp: Pointer to the result timespec structure where the difference is stored.
*
* The macro calculates the difference in seconds (tv_sec) and nanoseconds (tv_nsec).
* If the nanoseconds difference is negative, it adjusts the seconds and nanoseconds
* values accordingly to ensure the timespec remains normalized.
*/
#define timespecsub(tsp, usp, vsp) \
do { \
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
Expand All @@ -33,24 +47,44 @@
} \
} while (0)

/*
* Function to create a spinning delay for a given duration.
*
* Parameters:
* - duration_ns: The duration to spin in nanoseconds.
* - start_ts: The starting time as a timespec structure.
*
* This function uses a busy-wait loop to measure elapsed time from the provided start_ts
* until the specified duration in nanoseconds is reached. It calculates the elapsed time
* by repeatedly querying the current time and subtracting it from the start time.
*/
void spin2(uint64_t duration_ns, timespec& start_ts) {
uint64_t elapsed_ns = 0;

timespec curr_ts, diff_ts;
while(true) {
clock_gettime(CLOCK_REALTIME, &curr_ts);
timespecsub(&curr_ts, &start_ts, &diff_ts);
elapsed_ns = SEC_TO_NS(diff_ts.tv_sec) + diff_ts.tv_nsec;
clock_gettime(CLOCK_REALTIME, &curr_ts); // Get the current time
timespecsub(&curr_ts, &start_ts, &diff_ts); // Calculate the time difference
elapsed_ns = SEC_TO_NS(diff_ts.tv_sec) + diff_ts.tv_nsec; // Convert elapsed time to nanoseconds
if (elapsed_ns >= duration_ns) {
break;
break; // Exit the loop when the duration is met or exceeded
}
}
}

/*
* Function to create a spinning delay for a given duration in nanoseconds.
*
* Parameters:
* - duration_ns: The duration to spin in nanoseconds.
*
* This function records the start time, then delegates to spin2 to handle
* the spinning logic using the recorded start time.
*/
void spin(uint64_t duration_ns) {
timespec start_ts;
clock_gettime(CLOCK_REALTIME, &start_ts);
spin2(duration_ns, start_ts);
clock_gettime(CLOCK_REALTIME, &start_ts); // Record the start time
spin2(duration_ns, start_ts); // Delegate to spin2 with the recorded start time
}

namespace holoscan::ops {
Expand All @@ -62,14 +96,12 @@ class PingTxOp : public Operator {
PingTxOp() = default;

void setup(OperatorSpec& spec) override {
spec.output<int>("out"); //THIS WAS SETTING FOR EXPERIMENTS .condition(ConditionType::kNone);
//spec.output<int>("out2").condition(ConditionType::kNone);
spec.output<int>("out");
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
int value = index_++;
op_output.emit(value, "out");
//op_output.emit(value, "out2");
};

private:
Expand All @@ -85,14 +117,12 @@ class PingMxOp : public Operator {
void setup(OperatorSpec& spec) override {
spec.input<int>("in");
spec.output<int>("out").condition(ConditionType::kNone);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value);
Expand All @@ -113,14 +143,12 @@ class PingMxTwoOutputOp : public Operator {
spec.input<int>("in");
spec.output<int>("out1").condition(ConditionType::kNone);
spec.output<int>("out2").condition(ConditionType::kNone);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value, "out1");
Expand All @@ -140,16 +168,14 @@ class PingMxTwoOutputDownstreamOp : public Operator {

void setup(OperatorSpec& spec) override {
spec.input<int>("in");
spec.output<int>("out1"); //.condition(ConditionType::kNone);
spec.output<int>("out2"); //.condition(ConditionType::kNone);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.output<int>("out1");
spec.output<int>("out2");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value, "out1");
Expand All @@ -169,17 +195,15 @@ class PingMxThreeOutputDownstreamOp : public Operator {

void setup(OperatorSpec& spec) override {
spec.input<int>("in");
spec.output<int>("out1"); //.condition(ConditionType::kNone);
spec.output<int>("out2"); //.condition(ConditionType::kNone);
spec.output<int>("out3"); //.condition(ConditionType::kNone);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.output<int>("out1");
spec.output<int>("out2");
spec.output<int>("out3");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value, "out1");
Expand All @@ -200,18 +224,16 @@ class PingMxFourOutputDownstreamOp : public Operator {

void setup(OperatorSpec& spec) override {
spec.input<int>("in");
spec.output<int>("out1"); //.condition(ConditionType::kNone);
spec.output<int>("out2"); //.condition(ConditionType::kNone);
spec.output<int>("out3"); //.condition(ConditionType::kNone);
spec.output<int>("out4"); //.condition(ConditionType::kNone);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.output<int>("out1");
spec.output<int>("out2");
spec.output<int>("out3");
spec.output<int>("out4");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value, "out1");
Expand All @@ -234,15 +256,13 @@ class PingMultiInputMxOp : public Operator {
void setup(OperatorSpec& spec) override {
spec.param(receivers_, "receivers", "Input Receivers", "List of input receivers.", {});
spec.output<int>("out");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value_vector =
op_input.receive<std::vector<int>>("receivers").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value_vector[0]);
Expand All @@ -264,15 +284,13 @@ class PingMultiInputOutputMxOp : public Operator {
spec.param(receivers_, "receivers", "Input Receivers", "List of input receivers.", {});
spec.output<int>("out1");
spec.output<int>("out2");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value_vector =
op_input.receive<std::vector<int>>("receivers").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value_vector[0], "out1");
Expand All @@ -293,14 +311,12 @@ class PingMxDownstreamOp : public Operator {
void setup(OperatorSpec& spec) override {
spec.input<int>("in");
spec.output<int>("out");
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
auto value = op_input.receive<int>("in").value();

//std::cout << "Middle message value: " << value << std::endl;

spin((WCET_ * static_cast<double>(1000000)));

op_output.emit(value);
Expand All @@ -318,7 +334,7 @@ class PingRxOp : public Operator {

void setup(OperatorSpec& spec) override {
spec.param(receivers_, "receivers", "Input Receivers", "List of input receivers.", {});
spec.param(WCET_, "WCET", "WCET", "Worst case execution time", 0);
spec.param(WCET_, "WCET", "WCET", "Worst case execution time in milliseconds", 0);
}

void compute(InputContext& op_input, OutputContext& op_output, ExecutionContext&) override {
Expand All @@ -336,13 +352,13 @@ class PingRxOp : public Operator {
Parameter<int> WCET_;
};

} // namespace holoscan::ops

}
class MyPingApp : public holoscan::Application {
public:
void compose() override {
using namespace holoscan;

// This is filled in by MakeVars.py when the scripts are run


}
Expand Down
8 changes: 6 additions & 2 deletions tutorials/hsdk_rt_analysis/artifact/code/DAGResponseTime.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,14 @@ def get_response_time(DG, source, sink):

WCRTcandidates[node] = sourcetobottle + bottletosink


if node not in longestpath:
#An edge case can occur in large graphs where the longest path through the graph does not
#determine the response time.
#This is described in the paper in more detail
#For most graphs (including all practical examples) this below calculation results in
#significant execution time increases for no decrease in pessimism, so we disable it
#Note that the analysis is safe either way

#Huge execution time increase for less pessimism
if False:
#Find the path from the source to the node with the greatest sum of execution times
maxcost = 0
Expand Down
21 changes: 1 addition & 20 deletions tutorials/hsdk_rt_analysis/artifact/code/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@ def overheadmain():

graph.savefig("evaloverhead.pdf", bbox_inches='tight')




def scalabilitymain(graphs, constraint = False):

labels = ['20 edges', '40 edges', '60 edges', '80 edges', '100 edges']
Expand Down Expand Up @@ -141,13 +138,7 @@ def scalabilitymain(graphs, constraint = False):
predicted.close
simul.close





def scalabilitypess():


translate = dict([(19,0),(20,0), (39,1), (40, 1), (59,2), (60, 2),(79,3), (80, 3), (99,4), (100, 4)])
data = [[], [], [], [], []]

Expand Down Expand Up @@ -178,16 +169,9 @@ def scalabilitypess():

graphscaled.savefig("evalscalabilitypess.pdf", bbox_inches='tight')





def timinganalysis():

x = []
y = []


with open('analysistimes.txt', 'r') as timing:
for line in timing:
x.append(int(line.split(" ")[0]))
Expand All @@ -198,10 +182,8 @@ def timinganalysis():
# Create the scatter plot
plt.scatter(x, y, color='black', marker='x', label='A', s=20)


plt.yscale('log')
plt.ylim(1e-4, 1e1)


#Add labels
plt.ylabel('Analysis Time\n(seconds, log scale, base 10)', fontsize = 20, multialignment='center')
Expand All @@ -210,5 +192,4 @@ def timinganalysis():
plt.xticks(fontsize=15) # Increase x-axis tick labels font size
plt.yticks(fontsize=15) # Increase y-axis tick labels font size

graphanalysis.savefig("evalanalysis.pdf", bbox_inches='tight')

graphanalysis.savefig("evalanalysis.pdf", bbox_inches='tight')
2 changes: 1 addition & 1 deletion tutorials/hsdk_rt_analysis/artifact/experimentbase.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
%YAML 1.2
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2024 UNIVERSITY OF BRITISH COLUMBIA. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# This is a modified version of a file from the Holoscan SDK
Expand Down

0 comments on commit 3512363

Please sign in to comment.