LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

compare delay in CVI and labview

Hi there,

  I am comparing the precision of delay function in labview and in cvi. I have the code implemented to do the following

 

output digital pulse to DO1.2

wait(1ms)

output digital pulse to DO1.2

wait(2ms)

output digital pulse to DO1.2

wait(3ms)

output digital pulse to DO1.2

wait(5ms)

output digital pulse to DO1.2

wait(8ms)

output digital pulse to DO1.2

 

I scope the output for testing. If I implement this in labview with Delay function, I find that most of time it will delay as expected. But if I do the same thing in cvi by using Sleep function (from windows.h) or Delay function, about 30% the delay is too much off from my expect. So in this case, why CVI delay is not as good as labview?

 

 

0 Kudos
Message 1 of 12
(4,906 Views)

This is an interesting question: since it's a comparison between two languages, can you post the relevant code from both environments?

Better CVI2012 and LV 2010 or previous for me.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 12
(4,901 Views)

@RobertoBozzolo wrote:

This is an interesting question: since it's a comparison between two languages, can you post the relevant code from both environments?

Better CVI2012 and LV 2010 or previous for me.


I post the code, extracted from my program, for testing here.

 

#include "test.h"
#include <windows.h>
#include <formatio.h>
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>		
#include <userint.h>
#include <NIDAQmx.h>
#include "toolbox.h"

TaskHandle DOTaskID=NULL;

int main (int argc, char *argv[])
{
  InitCVIRTE (0, argv, 0);
  panelHandle = LoadPanel (0, "test.uir", PANEL);
  DisplayPanel (panelHandle);
  RunUserInterface();
  return 0;
}

int CVICALLBACK MainPanelResponse(int panel, int event, void *callbackData, int eventData1, int eventData2)
{
  if (event == EVENT_CLOSE) QuitUserInterface (0);
  return 0;
}

int CVICALLBACK test(void *data)
{ uInt8 val=1;
  #pragma omp parallel sections
  {
    #pragma omp section
    {
      DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL);
    }
    #pragma omp section
    {
      Sleep(5);
    }
  }
  
  #pragma omp parallel sections
  {
    #pragma omp section
    {
      DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL);
    }
    #pragma omp section
    {
      Sleep(3);
    }
  }
  
  #pragma omp parallel sections
  {
    #pragma omp section
    {
      DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL);
    }
    #pragma omp section
    {
      Sleep(12);
    }
  }
  
  #pragma omp parallel sections
  {
    #pragma omp section
    {
      DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL);
    }
    #pragma omp section
    {
      Sleep(2);
    }
  }
  
  return 0;
}

int CVICALLBACK RunButtonResponse(int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
  if (event==EVENT_COMMIT)
  {
    int threadFunId;
    DAQmxCreateTask(taskname, DOTaskID);   
    DAQmxCreateDOChan(DOTaskID, "Dev1/port0/line0", "", DAQmx_Val_ChanPerLine ));	
    CmtScheduleThreadPoolFunction(DEFAULT_THREAD_POOL_HANDLE, test, NULL, &threadFunId);	
    CmtWaitForThreadPoolFunctionCompletion(DEFAULT_THREAD_POOL_HANDLE, threadFunId, OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
    DAQmxStopTask(DOTaskID);
    DAQmxClearTask(DOTaskID);	
  }
  return 0;
}

 and the labview code is here

 

Untitled_1d.png

 

It seems the CVI code occupy more CPU resource. I scope the output. If the CPU is free, both codes give the about the same results. But in some case, if there is other application occupying the CPU, the delay in both code will be affected but cvi code delayed more than the labview one. I wonder if the Sleep in CVI same as the Wait function in labview? I don't know why but it seems that something about the priority.

0 Kudos
Message 3 of 12
(4,888 Views)

I was thinking about CVI sleep policy and its effect on program execution, but those #pragmas puzzle me: are you using an external compiler to generate the executable? And do you see this anomaly only in the IDE or in the executable as well?

 

I wander if parallel processing in this case cannot be a handicap more that a help: I seem to understand that each pragma directive causes the generation of a new thread where to execute the instructions, but with so short tasks this may add an unnecessary overhead to the system which could partially explain the erratic timing.

 

These considerations, however, come only from common sense as I have no experience in programming with OpenMP.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 4 of 12
(4,872 Views)

@RobertoBozzolo wrote:

I was thinking about CVI sleep policy and its effect on program execution, but those #pragmas puzzle me: are you using an external compiler to generate the executable? And do you see this anomaly only in the IDE or in the executable as well?

 

I wander if parallel processing in this case cannot be a handicap more that a help: I seem to understand that each pragma directive causes the generation of a new thread where to execute the instructions, but with so short tasks this may add an unnecessary overhead to the system which could partially explain the erratic timing.

 

These considerations, however, come only from common sense as I have no experience in programming with OpenMP.


Well, I don't know if version previous to CVI 2012 support OpenMP but in 2012, it supports directly. So it can be compiled directly. I am trying to use it because OpenMP will be easier but using the CmtScheduleThreadPoolFunction is a bit tedious. I don't know if they make any difference. Also the sleep policy seems not change much, I test it long time ago but not on this problem. I will test that again.

0 Kudos
Message 5 of 12
(4,867 Views)

What happens if you execute this plain code (it will pump CPU usage up to 100%):

 

int CVICALLBACK test (void *data)
{
uInt8 val=1;
int pol = GetSleepPolicy ();
double tini;
SetSleepPolicy (VAL_SLEEP_NONE);

tini = Timer ();
DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL); while (Timer () - tini < 5.0) {
ProcessSystemEvents ();
}
// and so on...
SetSleepPolicy (pol);
return 0; }

 

Also, this function definition resembles the one for a thread function spawned with CmtScheduleThreadPoolFunction: are you already trying to do some multithreading? Could this interfere with OpenMP instructions?



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 6 of 12
(4,855 Views)

In LabVIEW you are running both blocks simulteneously. (Delay and Digital pulse)

 

 

In CVI you are running sequencially.

 

Thanks.
CVI 2010
LabVIEW 2011 SP1
Vision Builder AI 2011 SP1
0 Kudos
Message 7 of 12
(4,836 Views)

@test_man wrote:

In LabVIEW you are running both blocks simulteneously. (Delay and Digital pulse)

 

 

In CVI you are running sequencially.

 


That's why I use OpenMP in CVI to make them running in parallel.

0 Kudos
Message 8 of 12
(4,833 Views)

@RobertoBozzolo wrote:

What happens if you execute this plain code (it will pump CPU usage up to 100%):

 

int CVICALLBACK test (void *data)
{
uInt8 val=1;
int pol = GetSleepPolicy ();
double tini;
SetSleepPolicy (VAL_SLEEP_NONE);

tini = Timer ();
DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL); while (Timer () - tini < 5.0) {
ProcessSystemEvents ();
}
// and so on...
SetSleepPolicy (pol);
return 0; }

 

Also, this function definition resembles the one for a thread function spawned with CmtScheduleThreadPoolFunction: are you already trying to do some multithreading? Could this interfere with OpenMP instructions?


I just test it again. It seems that using VAL_SLEEP_NONE helps improve the timing issue. It reduces the mistiming situtation. I try to run it 100 times and scope the output. About 90% of timing is correct but comparing to Labview, the mistiming rate is still too high.

 

In my testing, I am using Sleep. I try Delay but it is even worst. But I didn't try your code (using loop). I will test it later soon.

0 Kudos
Message 9 of 12
(4,818 Views)

@RobertoBozzolo wrote:

What happens if you execute this plain code (it will pump CPU usage up to 100%):

 

int CVICALLBACK test (void *data)
{
uInt8 val=1;
int pol = GetSleepPolicy ();
double tini;
SetSleepPolicy (VAL_SLEEP_NONE);

tini = Timer ();
DAQmxWriteDigitalLines(DOTaskID, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &val, NULL, NULL); while (Timer () - tini < 5.0) {
ProcessSystemEvents ();
}
// and so on...
SetSleepPolicy (pol);
return 0; }

 

Also, this function definition resembles the one for a thread function spawned with CmtScheduleThreadPoolFunction: are you already trying to do some multithreading? Could this interfere with OpenMP instructions?


I just test it with CmtScheduleThreadPoolFunction to spawn many threads to paralellize the code but it doesn't for short sleep. It will only work if sleep is so long. I think it is due to if you just want to sleep for few milliseconds, the time to create the threads, set/get policy and runing a pooling loop will be much longer than few milliseconds.

0 Kudos
Message 10 of 12
(4,814 Views)