How to deal with memory stack overload - c#

I am trying to programm an edge detection method. And I have used emgucv Image class. Since I need gray values I have declared it as
Image<Gray,float> MyImage = new Image<Gray,float>;
I select an image and assign its pixel values into MyImage as
public void selectImage()
{
OpenFileDialog opp = new OpenFileDialog();
if (opp.ShowDialog() == DialogResult.OK)
{
MyImage = new Image<Gray,float>(opp.FileName);
InputArray = new Image<Gray, float>(opp.FileName);
Convert.ToString(MyImage);
pictureBox1.Image = MyImage.ToBitmap();
}
}
When I click on edge detection button it calls the main recursive function
private void detect_edges_Click(object sender, EventArgs e)
{
hueckel_operator(1, 1);
}
This operator repeats itself with 5pixel intervals. In other words I apply it on x axis by incrementing x parameter by 5 and at the end of the row I increment y axis by 5 and so on.
In hueckel_operator, the function "a()" which calculates again a very heavy formula is being called 8 times. Here is the a() function
public double a(int j, int counter6, int counter7)
{
for (int II = 0; II <= j ; II++)
{
for (KK = 1; KK < 70; KK++)
{
x_value = input_i_x(KK); //this function brings the x coordinate
y_value = input_i_y(KK); // this function brings the y coordinate
result += HueckelDisk(x_value,y_value,j) * MyImage[x_value+counter6, y_value+counter7].Intensity;
//MyImage.Dispose();
}
}
return result;
}
But the problem is approximately at the coordinate (75,5) it throws a stack overflow exception. I debugged it with performance analyse and MyImage seems to eat all memory. You probably wants to see recursive function but since it is too big I can not put it here and I am sure that recursive function (hueckel_operator()) can not reach terminating condition since I found out how many times it has been called. What I want is to find out if there is another way to calculate "result" in a more efficient way.
My other question is that, object MyImage is used in function a() 69*j times and does it mean that it allocates memory space 69*j times whenever a() is called?
During my desperate tries, I have declared and defined almost every variable as global in order to reduce the memory usage because I have thought otherwise whenever hueckel_operator() and a() are called, local variables would allocate extra memory in stack over and over, is it a good or necessary approach?
I use 4 very nested and heavy functions and I don't use any class. Would it be the main problem? To be honest I don't see anything here to convert into class.
I know, I have asked too many questions but I am really desperate right now. I am reading articles since some weeks and I guess I need a kick start. Any help would be appreciated.

A stack overflow exception doesn't really have much to do with memory usage - it's from stack usage. In your case, a recursive call.
Recursion can only go so deep until the stack is exhausted. Once that happens, you get your stack overflow.
If you are not in an unbounded recursion but you need to go deeper, you can specify the stack size when you create a thread, and run your recursive function on that:
var stackSize = 10000000;
var thread = new Thread(new ThreadStart(StartDetection), stackSize);
However, the default size is 1MB - which is quite a bit for most tasks. You may want to verify your recursion is in fact not unbound, or that you can't reduce or remove it.

Related

Drawing data obtained from Serial Port progresively getting slower

I am working on voltmeter application, that draws voltage waveform. Hardware sends 1000 numbers (range 0 - 1023, always whole numbers) in string format per second through serial port.
public SerialPort serialPort = new SerialPort("COM3", 57600);
serialPort.Open();
String is converted into int and then drawn with DrawLine into PictureBox.
// variable declarations, all is int, runs in its own thread
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
iY = Int16.Parse(serialPort.ReadLine());
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
Issue is that drawing lines itself is fast as it should be only for a couple of seconds, but gets gradually slower.
I tried Int.Parse, Int32.Parse and splitting thread function multiple ways using lock (graphicsGraph) (moving conditions with Clear into another thread) or using BlockingCollection<int> (moving DrawLine into another thread, away from Parse). Nothing seems to work and app still gets slower a couple of times after like a minute of running.
There isn't issue with hardware itself, checked with another software. Is this too fast for C#?
Solution:
I got the best results using Port.ReadTimeout = 1 and Port.DiscardInBuffer(). Also using Form.DoubleBuffered = true, but it doesn't make a huge difference in this particular case.
// constructor
Port.ReadTimeout = 1;
Form.DoubleBuffered = true;
Here is the loop itself:
btn.Click() // click to start measuring
{
Port.DiscardInBuffer();
blToMeasure = true;
}
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
try {
iY = Int16.Parse(serialPort.ReadLine());
}
catch
{
// exception logic
}
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
When the app starts to read from the port, there is always accumulated data, because my hardware is sending numbers all the time, so I get rid of the buffer. Than the drawing of lines is not executed in differing spikes and the speed is constant. Analyzing the issue with Watch, I found out, that it occasionaly takes much longer to read this data and because of 1000 reads per second, it slows down. So to prevent slowing down, I used Port.ReadTimeout, that skips the read, if it takes too long.
The difference is visible, drawing no longer slows down and it keeps the same pace for minutes from what I've tried. I consider this sufficient solution for my issue, thank you!

Multiple threads calling the same function doesn't work

I have this code, and have a function named STARTWORK(int THREADNR) which cannot be called by 2 threads. Basically all the work of my program is contained in this function, where in the WORKVOID1() and WORKVOID2() i use separate for() functions to run through the data, and the for() function is split in half so that the 2 functions cover half-half of the data to be much faster and work on multicore processor.The problem is that if there is only the main thread, it works like a charm, but if i try to split the STARTWORK() into 2 parts in WORKVOID1() and WORKVOID2() each in multiple threads it doesn't work, so please help me fix it.
public void OPTIMIZATION_ITERATION()
{
Thread WORK = new Thread(WORKVOID);
WORK.Name = "T1";
WORK.Start();
Thread WORK2 = new Thread(WORKVOID2);
WORK2.Name = "T2";
WORK2.Start();
}
public void WORKVOID()
{
for (ALPHA = 0.001; ALPHA <= 0.5; ALPHA += 0.001)
STARTWORK(1);
}
public void WORKVOID2()
{
for (ALPHA = 0.5; ALPHA <= 1; ALPHA += 0.001)
STARTWORK(2);
}
public void STARTWORK(int THREAD)
{
//.......bunch of calculations then it writes it to file
System.IO.StreamWriter WRITE = new System.IO.StreamWriter("OUTPUT_T"+THREAD+".txt", true);
WRITE.BaseStream.Seek(0, SeekOrigin.End);
WRITE.WriteLine(/*..calculations are written to file..*/);
WRITE.Close();
WRITE.Dispose();
}
The STARTWORK(int THREADNR) contains a parameter which will assign a number that will write the data to file so that the 2 will have different filenames, while ALPHA is a global double variable.
if your working in c# you might want to try this.
public void OPTIMIZATION_ITERATION()
{
Thread WORK = new Thread(new ThreadStart(WORKVOID));
WORK.Name = "T1";
WORK.Start();
Thread WORK2 = new Thread(new ThreadStart(WORKVOID2));
WORK2.Name = "T2";
WORK2.Start();
}
public void WORKVOID()
{
for (ALPHA = 0.001; ALPHA <= 0.5; ALPHA += 0.001)
STARTWORK(1);
}
public void WORKVOID2()
{
for (ALPHA = 0.5; ALPHA <= 1; ALPHA += 0.001)
STARTWORK(2);
}
I think the problem is ALPHA. As soon as you start the second thread you set it equal to the condition that the first thread is looking for (ALPHA <= .5), then the first thread increments ALPHA by .001. The net result is that the first thread is highly unlikely to write anything to the file (maybe one line, depending on timing).
Beyond that, I don't really see the point of trying to to do this in parallel, if you are writing to the same disk, it's not going to help anything. If the calculations you are doing are CPU intense, then it might be a better approach to make the calculations parallel and then write everything to disk after it's done, or in chunks if memory is an issue.
Global variables such as ALPHA cannot be used safely in multi-threaded contexts. This is because both threads are allowed to read/write at the exact same time which causes a race condition. I recommend you change your work methods to accept a double parameter. That way, each method would be using a local variable instead of a global shared variable.

Variable not holding value

I'm working through a book that is helping me learn C#, and one of the projects is something like one of those old games one is taught in elementary powerpoint lessons. This particular example uses a for loop that defines how many exits (external doors) a room or area has.
This is an example of moving through an external door. When I go back through the door, using the "MoveToANewLocation()" method, "currentLocation" loses it's value. The for loop subsequently sets the value to a negative, resulting in an error.
private void MoveToANewLocation(Location newLocation)
{
currentLocation = newLocation;
exits.Items.Clear();
for (int i = 0; i < currentLocation.Exits.Length; i++)
{
exits.Items.Add(currentLocation.Exits[i].Name);
}
exits.SelectedIndex = 0;
description.Text = currentLocation.Description;
if (currentLocation is IHasExteriorDoor)
{
goThroughTheDoor.Visible = true;
}
else
{
goThroughTheDoor.Visible = false;
}
}
I have a reference example that is exactly the same as the above, which works. I am stumped as to why currentLocation is losing it's value when the button "goThroughTheDoor" invokes the "MoveToANewLocation()" method.
Apologies if this is unclear, I am still very new to modern programming
When the MoveToANewLocation method begins, it sets currentLocation to a copy of the parameter, newLocation:
//currentLocation = newLocation;
The currentLocation goes out of scope when the method exits and the garbage collector can clean up to use that memory for in scope objects. This explains how its value is lost after exiting the method.

NAudio fft result gives intensity on all frequencies C#

I have a working implementation of NAudio's wasapi loopback recording and the FFT of the data.
Most of the data I get is just as it should be but every once in a while (10 sec to minutes intervals) it shows amplitude on almost all frequencies.
Basicly the picture is rolling from right to left with time and frequencies going on logarithmic scale from lowest frequencies on the bottom. The lines are the errors. As far as i can tell those are not supposed to be there.
I get the audio buffer and send the samples to an aggregator (applies Hamming window) which implements the NAudio FFT. I have checked the data (FFT result) before I modify it in any way (the picture is not from the raw FFT output, but desibel scaled) confirming the FFT result is giving those lines. I could also point out the picture is modified with LockBits so I thought I had something wrong with the logic there, but that's why I checked the FFT output data which shows the same problem.
Well I could be wrong and the problem might be somewhere I said it isn't but it really seems it originates from the FFT OR the buffer data (data itself or the aggregation of samples). Somehow I doubt the buffer itself is corrupted like this.
If anyone has any idea what could cause this I would greatly appreciate it!
UPDATE
So I decided to draw the whole FFT result range rather than half of it. It showed something strange. I'm not sure of FFT but I thought Fourier transformation should give a result that is mirrored around the middle. This certainly is not the case here.
The picture is in linear scale so the exact middle of the picture is the middle point of the FFT result. Bottom is the first and top is the last.
I was playing a 10kHz sine wave which gives the two horizontal lines there but the top part is beyond me. It also seems like the lines are mirrored around the bottom quarter of the picture so that seems strange to me as well.
UPDATE 2
So I increased the FFT size from 4096 to 8192 and tried again. This is the output with me messing with the sine frequency.
It would seem the result is mirrored twice. Once in the middle and then again on the top and bottom halves. And the huge lines are now gone.. And it would seem like the lines only appear on the bottom half now.
After some further testing with different FFT lengths it seems the lines are completely random in that account.
UPDATE 3
I have done some testing with many things. The latest thing I added was overlapping of samples so that I reuse the last half of the sample array in the beginning of the next FFT. On Hamming and Hann windows it gives me massive intensities (quite like in the second picture I posted) but not with BlackmannHarris. Disabling overlapping removes the biggest errors on every window function. The smaller errors like in the top picture still remain even with BH window. I still have no idea why those lines appear.
My current form allows control over which window function to use (of the three previously mentioned), overlapping (on/off) and multiple different drawing options. This allows me to compare all the affecting parties effects when changed.
I shall investigate further (I am quite sure I have made a mistake at some point) but good suggestions are more than welcome!
The problem was in the way I handled the data arrays. Working like a charm now.
Code (removed excess and might have added mistakes):
// Other inputs are also usable. Just look through the NAudio library.
private IWaveIn waveIn;
private static int fftLength = 8192; // NAudio fft wants powers of two!
// There might be a sample aggregator in NAudio somewhere but I made a variation for my needs
private SampleAggregator sampleAggregator = new SampleAggregator(fftLength);
public Main()
{
sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
sampleAggregator.PerformFFT = true;
// Here you decide what you want to use as the waveIn.
// There are many options in NAudio and you can use other streams/files.
// Note that the code varies for each different source.
waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += OnDataAvailable;
waveIn.StartRecording();
}
void OnDataAvailable(object sender, WaveInEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler<WaveInEventArgs>(OnDataAvailable), sender, e);
}
else
{
byte[] buffer = e.Buffer;
int bytesRecorded = e.BytesRecorded;
int bufferIncrement = waveIn.WaveFormat.BlockAlign;
for (int index = 0; index < bytesRecorded; index += bufferIncrement)
{
float sample32 = BitConverter.ToSingle(buffer, index);
sampleAggregator.Add(sample32);
}
}
}
void FftCalculated(object sender, FftEventArgs e)
{
// Do something with e.result!
}
And the Sample Aggregator class:
using NAudio.Dsp; // The Complex and FFT are here!
class SampleAggregator
{
// FFT
public event EventHandler<FftEventArgs> FftCalculated;
public bool PerformFFT { get; set; }
// This Complex is NAudio's own!
private Complex[] fftBuffer;
private FftEventArgs fftArgs;
private int fftPos;
private int fftLength;
private int m;
public SampleAggregator(int fftLength)
{
if (!IsPowerOfTwo(fftLength))
{
throw new ArgumentException("FFT Length must be a power of two");
}
this.m = (int)Math.Log(fftLength, 2.0);
this.fftLength = fftLength;
this.fftBuffer = new Complex[fftLength];
this.fftArgs = new FftEventArgs(fftBuffer);
}
bool IsPowerOfTwo(int x)
{
return (x & (x - 1)) == 0;
}
public void Add(float value)
{
if (PerformFFT && FftCalculated != null)
{
// Remember the window function! There are many others as well.
fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HammingWindow(fftPos, fftLength));
fftBuffer[fftPos].Y = 0; // This is always zero with audio.
fftPos++;
if (fftPos >= fftLength)
{
fftPos = 0;
FastFourierTransform.FFT(true, m, fftBuffer);
FftCalculated(this, fftArgs);
}
}
}
}
public class FftEventArgs : EventArgs
{
[DebuggerStepThrough]
public FftEventArgs(Complex[] result)
{
this.Result = result;
}
public Complex[] Result { get; private set; }
}
And that is it I think. I might have missed something though.
Hope this helps!

C# multi-thread approach in GUI

I'm developing a small app. Need your help.
I have a table of 10 columns. Say, i select 5 rows in a list view.
I take all the values of col_1, in a list, pass it to a method.
If all values are equal, set combo_box1 value = "equal" else value = "not equal".
Current Approach:
I have 10 lists ( seems pretty lame... isn't it? i had asked a ques regarding this...), one for each col.
10 calls to the method that checks for equality of values, each for one list. Subsequently, set the combo box's(10 combo boxes) values.
If i have say 100 records, i guess the time taken will increase. So, i thought of implementing threads.
Effort Put:
I have used the this.Invoke(new Delegate...) approach for a thread which tries to access a control of Main thread. It works fine. I tried to manipulate this according to my needs. Couldn't do so. Please help me out guys.
[EDIT]
the main culprit was the image comparison... its taking awfully long time to finish... below is the code...
i'm storing all the image(say col no 3) of say 10 rows in a list...
// other stuffs
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern int memcmp(IntPtr b1, IntPtr b2, long count);
// create a list of images
MemoryStream imageStream = new MemoryStream(tempImage.Data.Data);
Bitmap artCoverImage = new Bitmap(imageStream); // culprit ?
artCoverList.Add(artCoverImage);
// call the method
CheckIfEqual(artCoverList) // culprit ?
// THE method
private void CheckIfEqual(artCoverList)
{
Bitmap tempBitMap = artCoverList[0];
foreach (Bitmap bmp in artCoverList)
{
if (bmp == null)
return false;
if (bmp.Size != tempBitMap.Size)
return false;
var bd1 = tempBitMap.LockBits(new Rectangle(new Point(0, 0), tempBitMap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
IntPtr bd1scan0 = bd1.Scan0;
int stride = bd1.Stride;
long len = stride * tempBitMap.Height;
var bd2 = bmp.LockBits(new Rectangle(new Point(0, 0), bmp.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
IntPtr bd2scan0 = bd2.Scan0;
returnValue = memcmp(bd1scan0, bd2scan0, len) == 0;
bmp.UnlockBits(bd2);
tempBitMap.UnlockBits(bd1); } }
I had spent a whole day to get this part image comparison working... i think the part where it converts mem stream to bmp is the culprit...
[EDIT 2]
guys...need your help... any idea... how to compare a list of images... other than above...
Thanks,
Dev
I would say that instead of using Invoke, check out BackgroundWorker . It has callback events that automatically run on the main thread, so it makes updating your UI when you're done easier, so as to avoid cross thread UI exceptions.
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += (s, e) => updateUI();
worker.DoWork += (s, e) => longProcess();
worker.RunWorkerAsync();
Implementing a threaded design has its own overhead and adds complexity. You really only want to consider moving to a threaded model if performance is poor enough to warrant the added complexity.
If you have 100 rows and you are checking equality of 10 columns, then you're doing 1000 equality checks. Depending on the implementation, this should be a trivial operation with negligible performance ramifications.
Consider profiling your application to see if there is a performance issue.
EDIT
Based on your findings (that image comparison is the culprit), you may want to consider using a simple checksum comparison against the respective image byte arrays.
Here is an example of how to do so:
http://www.dreamincode.net/code/snippet2859.htm
Note: MD5 is sufficient in this case and should prove to be slightly faster.
One way to check if all elements in a list are the same is to stuff them into a HashSet and check the amount of items in the HashSet afterwards: If you only have one item, then they are all equal...

Categories

Resources