Too many threads being used then jobqueue can handle.......

Too many threads being used then jobqueue can handle.......

I must be the only guy in the forum who always, always, ALWAYS has trouble setting up havok.....anyways, i rewrote the code a bit differently........and lo and behold i get this assertion.......

and of course here is my lovely code:

#include "CPhysicsManager.h"

namespace Ogre
{
namespace Physics
{
	PhysicsManager::PhysicsManager()
	{
		// This constructor will initialize
		// the physics engine

		// This is one of the main components needed
		// for the physics engine to be created;
		hkMemoryRouter* m_pMemoryRouter = hkMemoryInitUtil::initDefault();
		// This fully creates the system (but there's more work to do).
		hkBaseSystem::init(m_pMemoryRouter,PhysicsErrors);

		//This replaces the error function with our own
		hkError::replaceInstance(new Ogre::Physics::CPhysicsError(PhysicsErrors));

		// Make a variable to hold how many threads we'll use.
		int m_ptotalThreads;

		// This function gets the hardware information
		(in this case - how many threads it should use based on the
		CPU's threads).
		hkHardwareInfo* m_pHardwareInfo = new hkHardwareInfo();
		// Now we get the hardware info.
		hkGetHardwareInfo(*m_pHardwareInfo);

		m_ptotalThreads = m_pHardwareInfo->m_numThreads;

		// Declare a variable to describe the CPU 
		job's thread Pool.
		hkCpuJobThreadPoolCinfo m_pthreadPoolCinfo;
		// Set the num of threads.
		m_pthreadPoolCinfo.m_numThreads = m_ptotalThreads;
		// This sets the timer's buffer per thread alloc;
		m_pthreadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;

		// Set the thread info in the creator class.
		this->m_pJobThreadPool = new hkCpuJobThreadPool(m_pthreadPoolCinfo);

		// Now we set the Job Queue's info;
		hkJobQueueCinfo m_pjobQueue;
		// This sets howmany threads we'll be using for havok
		m_pjobQueue.m_jobQueueHwSetup.m_numCpuThreads = m_ptotalThreads;
		// Now we set the info
		this->m_pJobQueue = new hkJobQueue(m_pjobQueue);
		// We resize the monitor stream to match the buffer size
		hkMonitorStream::getInstance().resize(200000);

		// We now create the havok world -
		this is where all the entites (physical entities)
		will reside.
		hkpWorldCinfo m_pWorldCinfo;

		// This sets the behavior of the the broad phase should an entity get out of the bounds of the world;
		m_pWorldCinfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY;
		// This sets the world's size
		m_pWorldCinfo.setBroadPhaseWorldSize(12000.0f);
		// This sets the simulation tyoe (Multi-threaded);
		m_pWorldCinfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;

		// And now we create the world object
		this->m_pWorld = new hkpWorld(m_pWorldCinfo);

		// Now we mark the world for writing to it
		m_pWorld->markForWrite();
		// We then register the job queue
		m_pWorld->registerWithJobQueue(this->m_pJobQueue);
		// We then register all collision agents.
		hkpAgentRegisterUtil::registerAllAgents(m_pWorld->getCollisionDispatcher());

		// Now we set up the visual debugger.
		hkArray m_pProcContexts;

		// We create a new object of hkpPhysicsContext().
		this->m_pPhysicsContext = new hkpPhysicsContext();
		// We now register the contexts
		hkpPhysicsContext::registerAllPhysicsProcesses();
		//We add the world to the context so the visual debugger can "see: it.
		this->m_pPhysicsContext->addWorld(this->m_pWorld);
		// We push back the context
		m_pProcContexts.pushBack(this->m_pPhysicsContext);

		// We create a new instance of the visual debugger.
		this->m_pVisualDebugger = new ::hkVisualDebugger(m_pProcContexts);

		// We now set the visual debugger to start to "see" the world
		m_pVisualDebugger->serve();

		// We now close the world for writing
		m_pWorld->unmarkForWrite();
	}

	PhysicsManager::~PhysicsManager()
	{
		hkBaseSystem::quit();
		hkMemoryInitUtil::quit();
	}

	void PhysicsManager::update()
	{
		//m_pWorld->markForWrite();
		this->m_pWorld->stepMultithreaded(this->m_pJobQueue,this->m_pJobThreadPool,1.0f/60.0f);
		this->m_pPhysicsContext->syncTimers(this->m_pJobThreadPool);
		this->m_pVisualDebugger->step();
		hkMonitorStream::getInstance().reset();
		m_pJobThreadPool->clearTimerData();
		//m_pWorld->unmarkForWrite();
	}
};
};

lovely, isn't it?

LOL honestly i'm surprised i haven't been banned from being too annoying on these forums.

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hey havokisking3344,

No worries on the questions... they'll surely help out others who also encounter these types of 'gotchas'. It looks like you're initializing a thread pool (which creates worker threads) of the same 'thread size' as your job queue, but not accounting for the fact that the main thread (the one being used to create your thread pool) is also going to be pulling jobs from it. So you actually are having 'n+1' threads pulling jobs from a queue only setup to service 'n' threads. You should be able to get past this by changing this:

m_pthreadPoolCinfo.m_numThreads = m_ptotalThreads;

to this:

m_pthreadPoolCinfo.m_numThreads = m_ptotalThreads - 1;

Our 'SimpleMultithreadedConsoleMain' is probably a good point of reference on how to setup multithreading here.

Hope that helps!

Chris

Developer Support Engineer
Havok
www.havok.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today