The pseudo-codes below shows a typical Round Robin software architecture. If every device requires 20ms to service and UpdateLCD() requires 10ms to execute, what is the worst case response time?
void main (void) {
while(1) {
if (!! Device A needs Service) {
!! Handle Device A
}
if (!! Device B needs Service) {
!! Handle Device B
}
. . . .
if (!! Device D needs Service) {
!! Handle Device D
}
UpdateLCD();
}
}
Since there are a total of 4 devices (A,B,C,D) and if immediately after servicing Device A, Device A needs servicing, the worst case response time here should be 20+20+20+10 = 70ms (assuming Devices B, C and D also needs servicing).
However, in the answer selection, there is only: 85ms, 110ms, 35ms and 25ms. I think i need help on my understanding of the round robin architecture.. Thanks!
First, your math is wrong: if there are four devices (A, B, C, and D), then the worst case time is 20*4 + 10 = 90ms.
By process of elimination, though, it can't be 85, 35, or 25 (since the provided times are all multiples of 10), so the "correct" answer must be 110… but this would assume five devices, not four.
Related
I am looking at the basic BLE_Scan.ino sketch from the ESP32_BLE_Arduino library. I've modified it to do 5 scans in a row before anything else. I would like to do a few scans very quickly in order to average them. (See code below)
I cannot figure out the difference between scan interval, scan window and the scanTime paramter.
I understand that the window should be how long to scan, this should happen every interval. I am not sure waht the scanTime paramamter does.
I have adjusted the scan interval and scan window to low numbers. Have also put the scanTime variable as low as it can be (1, since it is an int, and it cannot be 0). None of these fixes seem to allow me to do quick scan. Still seems to have a second or two delay between printing "scan!!" each time.
Any help in clarifying what these 3 parameter do, or can point out what I am doing wrong is appreciated.
(Also, my first post on SO, so let me know if I can fix up how I have asked this question, and I will!)
Thanks!!
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 1; //In seconds
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(50); //interval (how often there is a scan)
pBLEScan->setWindow(49); // window (how long the scans are) must be <= interval
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
//bluetooth scan
for(int x = 0; x < 5; x ++){
BLEScanResults foundDevices = pBLEScan->start(1, true);
Serial.println("Scan!!");
}
delay(200);
}
The Scan_Window configuration parameter defines the amount of time for the duration of the scan. The Inquiry_Scan_Window can only be less than or equal to the Scan_Interval. [Time Default: 11.25 ms]
The Scan_Interval configuration parameter defines the amount of time between consecutive scans. This is defined as the time interval from when the BR/EDR Controller started its last scan until it begins the next scan. [Default: 2.5 sec]
Scan Timeout: A device may scan for a limited duration of time
It is a homework and I have completely NO idea, my teacher says you need just while, analogWrite and a counter. I have a DC motor, a transistor and a 9V battery.
I know my code does NOTHING, but just as example.
int analogPin = 3;
int count = 0;
void setup()
{
pinMode(analogPin, OUTPUT);
}
void loop() {
while(count<30){
analogWrite(analogPin , 255);
delay(20000);
count++;
}
}
You need to use counter value as your analogue output value:
void loop()
{
if( count < 256 )
{
analogWrite( analogPin, count ) ;
delay( 20000 );
count++ ;
}
}
Note that you do not need a while loop; the Arduino framework already calls loop() iteratively (the clue is in the name). However if your teacher thinks you need one and is expecting one, you may need to use one just for the marks. Alternatively discuss it with your teacher, and explain why it is unnecessary
In fact the delay too is arguably bad practice - it is unhelpful in applications where the loop() must do other things while controlling the motor. The following allows other code to run whilst controlling the motor:
unsigned long delay_start = 0 ;
void loop()
{
if( count < 256 &&
millis() - delay_start >= 20000ul )
{
analogWrite( analogPin, count ) ;
count++ ;
delay_start = millis() ;
}
// Do other stuff here
}
Because the loop() now never blocks on the delay() function, you can have code that does other things such as read switch inputs and it can react to them instantly, whereas as in your solution, such inputs could be ignored for up-to 20 seconds!
A typical DC motor will not start moving at very low values - you may want to start count somewhat higher than zero to account for the "dead-band". Analogue signals are also generally a poor way to drive a DC motor and varying speed; a PWM is generally a more efficient method, and will allow the motor to run at lower speeds. With an analogue signal at low levels (lower than for PWM), your motor will not move and will just get warm and drain your battery.
For test purposes, reduce the delay time; you don't want to sit there for an hour and 25 minutes just to find the code does not work! Set it to say 500ms, then start it, time how long it takes before the motor starts to move. If that is say 30 seconds, then yu know the motor starts to move when count is about 60; in which case that is a better starting value that zero. Then you can increase your delay back to 20 seconds if you wish - though a DC power supply might be better than a battery - I'm not sure it will last that long.
I am programming performance-sensitive code. I implement a simple scheduler to distribute workloads and master thread takes charge of the scheduler.
cpu_set_t cpus;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i_group =0; i_group<n_groups; i_group++){
std::cout << i_t<< "\t"<<i_group << "th group of cpu" <<std::endl;
for(int i =index ; i < index+group_size[i_group]; i++){
struct timeval start, end;
double spent_time;
gettimeofday(&start, NULL);
arguments[i].i_t=i_t;
arguments[i].F_x=F_xs[i_t];
arguments[i].F_y=F_ys[i_t];
arguments[i].F_z=F_zs[i_t];
CPU_ZERO(&cpus);
CPU_SET(arguments[i].thread_id, &cpus);
int err= pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus);
if(err!=0){
std::cout << err <<std::endl;
exit(-1);
}
arguments[i].i_t=i_t;
pthread_create( &threads[i], &attr, &cpu_work, &arguments[i]);
gettimeofday(&end, NULL);
spent_time = ((end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6;
std::cout <<"create: " << spent_time << "s " << std::endl;
}
i_t++;
cpu_count++;
arr_finish[i_group]=false;
}
}
like above the master thread create. For the simple explanation, i will assume i_group=1. The child threads divide and conquer a bunch of matrix-matrix multiplications. Here rank means thread_id.
int local_first = size[2]*( rank -1 )/n_compute_thread ;
int local_end = size[2] * rank/n_compute_thread-1;
//mkl_set_num_threads_local(10);
gettimeofday(&start, NULL);
for(int i_z=local_first; i_z<=local_end; i_z++ ){
cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
size[0], size[1], size[0], 1.0, F_x, size[0],
rho[i_z], size[1], 0.0, T_gamma[i_z], size[1] );
}
for(int i_z=local_first; i_z<=local_end; i_z++ ){
cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
size[0], size[1], size[1], 1.0, T_gamma[i_z], size[0],
F_y, size[1], 0.0, T_gamma2[i_z], size[0] );
}
gettimeofday(&end, NULL);
std::cout <<i_t <<"\t"<< arg->thread_id <<"\t"<< sched_getcpu()<< "\t" << "compute: " <<spent_time << "s" <<std::endl;
Even though workload fairly distributed, the performance of each thread vary too much. see the result below
5 65 4 4 compute: 0.270229s
5 64 1 1 compute: 0.284958s
5 65 2 2 compute: 0.741197s
5 65 3 3 compute: 0.76302s
second column shows how many matrix-matrix multiplications are done in a particular thread. last column shows consumed time.
When I saw this result firstly, I thought that it related to the affinity of threads. Thus, I added several lines to control the binding of threads. However, it did not change the trends of last column.
My computer has 20 physical cores and 20 virtual core. I made only 4 child threads to test. Of course, it was tested in a Linux machine.
Why does the performance of the threads vary so much? and How to fix it?
First, are you actually creating a scheduler? Your code sample suggests that you are using Linux scheduler and setting thread attributes object, and thread affinity parameters, etc. This difference is relevant in choosing how to approach the problem.
In any case, the question is big, and there are several additional questions/topics that could be raised to help clarify the conditions, and move closer to a real answer. To start, here are some things to consider:
1 - Length of benchmark test. Sub-second evaluation of thread performance within a pool of threads seems inadequate. Stretch the evaluation time to allow the scheduler time to settle. Perhaps several minutes.
( For an example of typical duration times used in an existing benchmarking utility, read this )
2 - Thread priorities. Your threads are not the only ones. Is it possible the kernel scheduler may be periodically moving the benchmark around as threads belonging to other processes (other than the ones you have created) that have a higher priority? (and therefore are displacing yours, resulting in skewing the task completion time)
3 - Size of task. Is the number of operations required to complete each task small enough to fit within the time-slice allocated by the scheduler? This could possibly contribute to the perception of thread to thread performance issues, especially if there are any differences in the number of operations between each task. ( Processes that exceed the allotted
CPU time slice are automatically moved down to a lower “tier,” while processes that make I/O requests or block will be moved to higher “tiers.” )
4 - Equality of tasks - You mention divide and conquer a bunch of matrix-matrix multiplications. But are the matrices identical in size and similar in content. i.e., are you certain the count of operations in each task is equivalent the the count of operations in all the other tasks? The time slice allocated by the scheduler to each equally prioritized thread will ensure that over time a task having an operation count larger than that can be completed in a single time-slice will be more susceptible to longer completion times ( context switching due to higher priority of other OS processes) than those having few enough operations to fit comfortable within one time slice.
5 - Other processes. I have mentioned this in other items above, but it deserves its own number. In order to use multiple cores, multiple threads are required at the same time. But the inverse is not true. A single core is not limited to a single thread. The OS can at any time preemptively interrupt one of your processes (threads) on a particular core with a higher priority process, (while not interrupting any other core) possibly skewing your time measurement. Again, a longer benchmarking time will serve to reduce the impact of thread to thread differences caused by this particular phenomena.
Using a deque of structs that look like this:
struct{
int ID;
int arrivalTime;
int burstTime;
};
How would I step through the deque of structs so that if the input where like this:
0 0 3
1 5 2
3 8 4
where each row is a struct's ID, arrivalTime, and burstTime respectively, I would be able to print out something like this:
Time 0 Process 0 is running
Time 2 Process 0 is running
Time 3 Processor is Idle
Time 5 Process 1 is running
Time 7 Processor is Idle
Time 8 Process 3 is running
Time 10 Process 3 is running
this output is assuming a time quantum of 2. Is there a way to do this with just one deque or would it be easier to create another deck as a FIFO queue to process this? I know I'll need an integer to keep track of how much time has elapsed, but other than that this problem is really stumping me. Its the idle time that throws me off. Any help in C++ code or even psuedocode would really help. Thanks!
I know I'll need an integer to keep track of how much time has elapsed
I would start with three values - elapsed time, current process and next process. Your scheduling loop might look something like below. I've put the logic choosing next process to a standalone function for the sake of simplicity:
time = 0;
currentProcess = deque.end();
while(some processes remaining)
{
nextProcess = getNextProcess(time, currentProcess, deque);
if(nextProcess->arrivalTime > time)
{
// nothing to do now
// advance time by smaller of quota or nextProcess->arrivalTime
} else {
// at least one process has work ready
if(currentProcess != nextProcess)
{
// preemt currentProcess
// start nextProcess
// advance time by the smaller of quota or nextProcess->burstTime
// reduce nextProcess->burstTime by the time advanced
} else {
// continue with current process for quota or its remaining burstTime
// reduce its burstTime
}
}
currentProcess = nextProcess;
}
Implementing getNextProcess depends on your priority criteria, a naive approach might look like this:
You go through deque starting at position currentProcess + 1. When you hit the end, continue from beginning.
Take note of the process with smallest arrivalTime that is greater than time. Lets call it closestCandidate
If you find suitable process with arrivalTime <= time and burstTime > 0, return that
If you hit currentProcess again, decide between currentProcess and closestCandidate which is better to process and return that.
One last thing to do is to effectively implement the looping condition. I will leave that for you to figure out.
NOTE: Im not sure if deque is the best container here, I would pobably use forward_list and delete the processes as they finish. You could do this in the deque too, but thats O(n) operation.
I have a while loop that runs in a do while loop. I need the while loop to run exactly every second no faster no slower. but i'm not sure how i would do that. this is the loop, off in its own function. I have heard of the sleep() function but I also have heard that it is not very accurate.
int min5()
{
int second = 00;
int minute = 0;
const int ZERO = 00;
do{
while (second <= 59){
if(minute == 5) break;
second += 1;
if(second == 60) minute += 1;
if(second == 60) second = ZERO;
if(second < 60) cout << "Current Time> "<< minute <<" : "<< second <<" \n";
}
} while (minute <= 5);
}
The best accuracy you can achieve is by using Operating System (OS) functions. You need to find the API that also has a callback function. The callback function is a function you write that the OS will call when the timer has expired.
Be aware that the OS may lose timing precision due to other tasks and activities that are running while your program is executing.
If you want a portable solution, you shouldn't expect high-precision timing. Usually, you only get that with a platform-dependent solution.
A portable (albeit not very CPU-efficient, nor particularly elegant) solution might make use of a function similar to this:
#include <ctime>
void wait_until_next_second()
{
time_t before = time(0);
while (difftime(time(0), before) < 1);
}
You'd then use this in your function like this:
int min5()
{
wait_until_next_second(); // synchronization (optional), so that the first
// subsequent call will not take less than 1 sec.
...
do
{
wait_until_next_second(); // waits approx. one second
while (...)
{
...
}
} while (...)
}
Some further comments on your code:
Your code gets into an endless loop once minute reaches the value 5.
Are you aware that 00 denotes an octal (radix 8) number (due to the leading zero)? It doesn't matter in this case, but be careful with numbers such as 017. This is decimal 15, not 17!
You could incorporate the seconds++ right into the while loop's condition: while (seconds++ <= 59) ...
I think in this case, it would be better to insert endl into the cout stream, since that will flush it, while inserting "\n" won't flush the stream. It doesn't truly matter here, but your intent seems to be to always see the current time on cout; if you don't flush the stream, you're not actually guaranteed to see the time message immediately.
As someone else posted, your OS may provide some kind of alarm or timer functionality. You should try to use this kind of thing rather than coding your own polling loop. Polling the time means you need to be context switched in every second, which keeps your code running when the system could be doing other stuff. In this case you interrupt someone else 300 times just to say "are we done yet".
Also, you should never make assumptions about the duration of a sleep - even if you had a real time OS this would be unsafe - you should always ask the real time clock or tick counter how much time has elapsed each time because otherwise any errors accumulate so you will get less and less accurate over time. This is true even on a real time system because even if a real time system could sleep accurately for 1 second, it takes some time for your code to run so this timing error would accumulate on each pass through the loop.
In Windows for example, there is a possibility to create a waitable timer object.
If that's Your operating system check the documentation here for example Waitable Timer Objects.
From the code You presented it looks like what You are trying to do can be done much easier with sleep. It doesn't make sense to guarantee that Your loop body is executed exactly every 1 second. Instead make it execute 10 times a second and check if the time that elapsed form the last time, You took some action, is more than a second or not. If not, do nothing. If yes, take action (print Your message, increment variables etc), store the time of last action and loop again.
Sleep(1000);
http://msdn.microsoft.com/en-us/library/ms686298(VS.85).aspx