Sign in to follow this  

bad performance using _beginthread()

This topic is 3845 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I wrote a program to learn to perform XOR operations. It does this using a neural network. I wanted to write it to take advantage of my dual core processor, but after rewriting my function to spawn some worker threads the performance has dropped to less than 1% of what it originally was. Any help would be appreciated, I've been programming for a while, but this is the first time I've tried to use multiple threads. This is a C++ console application btw.
//NeuralLayer.h
#pragma once
#include "BaseNeuralLayer.h"
#include "Neuron.h"
#include <process.h>
#include <iostream>

using namespace std;

class NeuralLayer :
	public BaseNeuralLayer
{
public:
	void Pulse();
	void PulseMultiThreaded();
	void ApplyLearning();

	NeuralLayer(void);
	~NeuralLayer(void);
};

void ProcPulse(void *Data);

struct ProcPulseDataStruct
{
	bool *Status;
	Neuron *NeuronData;
};

//NeuralLayer.cpp
#include "NeuralLayer.h"

NeuralLayer::NeuralLayer(void)
{
}

NeuralLayer::~NeuralLayer(void)
{
}

void NeuralLayer::Pulse()
{
	for(int i = 0; i < (int)this->Neurons.size(); i++)
              this->Neurons[i]->Pulse();
}

//My attempt to make the above function multithreaded
void NeuralLayer::PulseMultiThreaded()
{
	int neuroncount = (int) this->Neurons.size();
//array of the status of each worker thread
	bool *threadrunning = new bool[neuroncount];
	uintptr_t Error;
	for(int i = 0; i < neuroncount; i++)
	{
		threadrunning[i] = false;
	}
//Spawn one thread for each neuron in this layer
	for(int i = 0; i < neuroncount; i++)
	{
		threadrunning[i] = true;
		ProcPulseDataStruct *Data = new ProcPulseDataStruct;
		Data->Status = &(threadrunning[i]);
		Data->NeuronData = (Neuron *) this->Neurons[i];
		//Create worker thread to pulse each neuron
		Error = _beginthread(ProcPulse, 0, (void *) Data);
		if(Error == 1L)
			cout << "Fatal error! Cannot create new thread" << __FILE__ << __LINE__ << endl;
	}
	bool done = false;
	//wait until all worker threads finish
	while(!done)
	{
		done = true;
		for(int i = 0; i < neuroncount; i++)
			if(threadrunning[i])
				done = false;
	}
	delete[] threadrunning;
}

void NeuralLayer::ApplyLearning()
{
	for(int i = 0; i < (int)this->Neurons.size(); i++)
	{
		this->Neurons[i]->ApplyLearning();
	}
}

void ProcPulse(void *Data)
{
	ProcPulseDataStruct *data = (ProcPulseDataStruct *) Data;
//Pulse the neuron
	data->NeuronData->Pulse();
//Set thread status to done
	*(data->Status) = false;
//Free memory
	delete data;
//Exit thread
	_endthread();
}

Share this post


Link to post
Share on other sites
Starting and stopping threads is pretty expensive on most OSes. You're basically beating the crap out of your OS and CPU here. There are two problems going on simultaneously: first, you're starting and stopping threads a lot, which is never a good idea. Secondly, you're using far too many threads.

In general, suppose you have N CPUs/CPU cores available; if your design involves more than 2*N threads, it will probably not perform well, generally speaking (that's a fast and loose rule but it's handy as a sanity check).

What you should probably do is run 2 threads, and assign each one a set of neurons to update, probably a 50-50 split. Make that assignment only once, when your program first starts, and keep the two threads alive. Instead of destroying and recreating a new thread all the time, just suspend the thread until you want it to run code again. This kind of approach is often referred to as thread pooling.

Even still, locking or suspending threads a lot is generally a bad sign. Your design should allow threads to run uninterrupted as much as possible.


You might have a look at the OpenMP project's design for some guidance in effective ways to use threading, particularly from C++ code. In fact, you might find it useful to just straight up use OpenMP, if your tools support it.

Share this post


Link to post
Share on other sites
Thanks, I was wondering if that was the problem. What function do I use to suspend a thread created with _beginthread()? I'll look into OpenMP, never heard of it before.

Share this post


Link to post
Share on other sites
Suspending and locking threads is generally very platform-specific; there is no standard CRT function for either operation. Depending on what OS(es) you plan on targetting, you'll have to look at various APIs. On Windows, you'd use SuspendThread and ResumeThread, for example.

Blending OS-specific thread calls with the CRT thread calls has some pitfalls, however; check the MSDN docs for details.

Share this post


Link to post
Share on other sites

This topic is 3845 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this