ocelot/ocelot/executive/implementation/LLVMCooperativeThreadArray.cpp
void LLVMCooperativeThreadArray::_executeComplexCta(unsigned int id)
{
	const unsigned int threads  = _contexts.size();

	const unsigned int warps   = threads / _warpSize;
	const unsigned int remains = threads % _warpSize;

	report(" warp size:        " << _warpSize);
	report(" full warps:       " << warps);
	report(" remaining threas: " << remains);
	report(" entry point:      " << _entryPoint);

	ThreadList warpList;

	unsigned int threadId = 0;

	report("Executing LLVM-CTA " << id << " (" 
		<< _functions[_nextFunction]->kernel->name << ")");

	for(unsigned int warp = 0; warp < warps; ++warp)
	{
		for(unsigned int thread = 0; thread != _warpSize; ++thread)
		{
			warpList.push_back(_initializeNewContext(threadId++, id));
		}
		
		_executeWarp(warpList.begin(), warpList.end());
		
		for(ThreadList::const_iterator context = warpList.begin();
			context != warpList.end(); ++context)
		{
			_reclaimContext(*context);
		}
		
		warpList.clear();
	}
	
	for(unsigned int thread = 0; thread != remains; ++thread)
	{
		warpList.push_back(_initializeNewContext(threadId++, id));
	}
	
	_executeWarp(warpList.begin(), warpList.end());
	
	for(ThreadList::const_iterator context = warpList.begin();
		context != warpList.end(); ++context)
	{
		_reclaimContext(*context);
	}
	
	warpList.clear();

	while(_freeContexts.size() + _reclaimedContexts.size() != threads)
	{
		report("  while( free + reclaimed contexts (" 
			<< (_freeContexts.size() + _reclaimedContexts.size()) 
			<< ") != threads (" << threads << ")");
	
		_computeNextFunction();
		
		warpList = std::move(_queuedThreads[_nextFunction]);
		
		const unsigned int threads = warpList.size();
		const unsigned int warps   = threads / _warpSize;
		const unsigned int remains = threads % _warpSize;

		report("Next sub-kernel is " << _nextFunction << " (" 
			<< _functions[_nextFunction]->kernel->name << ")");

		report(" threads:          " << threads);
		report(" full warps:       " << warps);
		report(" remaining threas: " << remains);
		
		ThreadList::const_iterator begin = warpList.begin();

		for(unsigned int warp = 0; warp != warps; ++warp)
		{
			ThreadList::const_iterator end = begin;
			std::advance(end, _warpSize);
			_executeWarp(begin, end);
			begin = end;
		}
	
		ThreadList::const_iterator end = begin;
		std::advance(end, remains);
		_executeWarp(begin, end);
		
		for(ThreadList::const_iterator context = warpList.begin();
			context != warpList.end(); ++context)
		{
			_destroyContext(*context);
		}

		warpList.clear();
	}
	
	_destroyContexts();
}
/* We want to execute the CTA as quickly as possibly. Speed is the only 
	concern here, but it requires careful thread scheduling and state 
	management to maximize the opportunities for locality and vector 
	execution. The current algorithm is as follows:
	
	Always issue threads with the widest vector width available.
	
	1) Start by launching threads in order, if they finish before exiting 
		the subkernel, then they die here and their state is reclaimed.  If they
		bail out due to divergence or hit a context switch point, then allocate
		a new thread context for the next thread and save the current thread
		context's id for scheduling in a queue for the next subkernel.  
	2) Sort the queues by thread count.  Pick the queue with the most waiting
		threads.
		a) If it has not been jitted yet, do so now.
		b) Group threads together into warps of fused kernel width 
			(possibly by sorting but FCFS should require less overhead).  
			Launch them all.
		c) If a thread exits, kill it and reclaim the state, otherwise move 
			it to another queue.
		d) If a thread hits a barrier, put it into a barrier queue.
		d) Once all threads have been launched we are done with this sub-kernel.
	3) Reorganize the threads
		a) If all threads are in the barrier queue, move them back into their
			correspoding queues.
		b) If there is at least one thread left in at least one queue, goto 2.
		c) If all threads are finished, the CTA is done.

*/
We want to execute the CTA as quickly as possibly. Speed is the only
concern here, but it requires careful thread scheduling and state
management to maximize the opportunities for locality and vector
execution. The current algorithm is as follows.

Always issue threads with the widest vector width available.

1) Start by launching threads in order, if they finish before exiting
the subkernel, then they die here and their state is reclaimed.  If they
bail out due to divergence or hit a context switch point, then allocate
a new thread context for the next thread and save the current thread
context's id for scheduling in a queue for the next subkernel.
2) Sort the queues by thread count.  Pick the queue with the most waiting
threads.
a) If it has not been jitted yet, do so now.
b) Group threads together into warps of fused kernel width
(possibly by sorting but FCFS should require less overhead).
Launch them all.
c) If a thread exits, kill it and reclaim the state, otherwise move
it to another queue.
d) If a thread hits a barrier, put it into a barrier queue.
d) Once all threads have been launched we are done with this sub-kernel.
3) Reorganize the threads
a) If all threads are in the barrier queue, move them back into their
correspoding queues.
b) If there is at least one thread left in at least one queue, goto 2.
c) If all threads are finished, the CTA is done.
We want to execute the CTA as quickly as possibly . Speed is the only concern here but it requires careful thread scheduling and state management to maximize the opportunities for locality and vector execution . The current algorithm is as follows . Always issue threads with the widest vector width available . 1 ) Start by launching threads in order if they finish before exiting the subkernel then they die here and their state is reclaimed . If they bail out due to divergence or hit a context switch point then allocate a new thread context for the next thread and save the current thread context ' s id for scheduling in a queue for the next subkernel . 2 ) Sort the queues by thread count . Pick the queue with the most waiting threads . a ) If it has not been jitted yet do so now . b ) Group threads together into warps of fused kernel width ( possibly by sorting but FCFS should require less overhead ) . Launch them all . c ) If a thread exits kill it and reclaim the state otherwise move it to another queue . d ) If a thread hits a barrier put it into a barrier queue . d ) Once all threads have been launched we are done with this sub - kernel . 3 ) Reorganize the threads a ) If all threads are in the barrier queue move them back into their correspoding queues . b ) If there is at least one thread left in at least one queue goto 2 . c ) If all threads are finished the CTA is done .
void LLVMCooperativeThreadArray::_executeComplexCta(unsigned int id)
{
	const unsigned int threads  = _contexts.size();
	const unsigned int warps   = threads / _warpSize;
	const unsigned int remains = threads % _warpSize;
	report(" warp size:        " << _warpSize);
	report(" full warps:       " << warps);
	report(" remaining threas: " << remains);
	report(" entry point:      " << _entryPoint);
	ThreadList warpList;
	unsigned int threadId = 0;
	report("Executing LLVM-CTA " << id << " (" 
		<< _functions[_nextFunction]->kernel->name << ")");
	for(unsigned int warp = 0; warp < warps; ++warp)
	{
		for(unsigned int thread = 0; thread != _warpSize; ++thread)
		{
			warpList.push_back(_initializeNewContext(threadId++, id));
		}
		_executeWarp(warpList.begin(), warpList.end());
		for(ThreadList::const_iterator context = warpList.begin();
			context != warpList.end(); ++context)
		{
			_reclaimContext(*context);
		}
		warpList.clear();
	}
	for(unsigned int thread = 0; thread != remains; ++thread)
	{
		warpList.push_back(_initializeNewContext(threadId++, id));
	}
	_executeWarp(warpList.begin(), warpList.end());
	for(ThreadList::const_iterator context = warpList.begin();
		context != warpList.end(); ++context)
	{
		_reclaimContext(*context);
	}
	warpList.clear();
	while(_freeContexts.size() + _reclaimedContexts.size() != threads)
	{
		report("  while( free + reclaimed contexts (" 
			<< (_freeContexts.size() + _reclaimedContexts.size()) 
			<< ") != threads (" << threads << ")");
		_computeNextFunction();
		warpList = std::move(_queuedThreads[_nextFunction]);
		const unsigned int threads = warpList.size();
		const unsigned int warps   = threads / _warpSize;
		const unsigned int remains = threads % _warpSize;
		report("Next sub-kernel is " << _nextFunction << " (" 
			<< _functions[_nextFunction]->kernel->name << ")");
		report(" threads:          " << threads);
		report(" full warps:       " << warps);
		report(" remaining threas: " << remains);
		ThreadList::const_iterator begin = warpList.begin();
		for(unsigned int warp = 0; warp != warps; ++warp)
		{
			ThreadList::const_iterator end = begin;
			std::advance(end, _warpSize);
			_executeWarp(begin, end);
			begin = end;
		}
		ThreadList::const_iterator end = begin;
		std::advance(end, remains);
		_executeWarp(begin, end);
		for(ThreadList::const_iterator context = warpList.begin();
			context != warpList.end(); ++context)
		{
			_destroyContext(*context);
		}
		warpList.clear();
	}
	_destroyContexts();
}
void LLVMCooperativeThreadArray :: _executeComplexCta ( unsigned int id ) { const unsigned int threads = _contexts . size ( ) ; const unsigned int warps = threads / _warpSize ; const unsigned int remains = threads % _warpSize ; report ( " " << _warpSize ) ; report ( " " << warps ) ; report ( " " << remains ) ; report ( " " << _entryPoint ) ; ThreadList warpList ; unsigned int threadId = 0 ; report ( " " << id << " " << _functions [ _nextFunction ] -> kernel -> name << " " ) ; for ( unsigned int warp = 0 ; warp < warps ; ++ warp ) { for ( unsigned int thread = 0 ; thread != _warpSize ; ++ thread ) { warpList . push_back ( _initializeNewContext ( threadId ++ , id ) ) ; } _executeWarp ( warpList . begin ( ) , warpList . end ( ) ) ; for ( ThreadList :: const_iterator context = warpList . begin ( ) ; context != warpList . end ( ) ; ++ context ) { _reclaimContext ( * context ) ; } warpList . clear ( ) ; } for ( unsigned int thread = 0 ; thread != remains ; ++ thread ) { warpList . push_back ( _initializeNewContext ( threadId ++ , id ) ) ; } _executeWarp ( warpList . begin ( ) , warpList . end ( ) ) ; for ( ThreadList :: const_iterator context = warpList . begin ( ) ; context != warpList . end ( ) ; ++ context ) { _reclaimContext ( * context ) ; } warpList . clear ( ) ; while ( _freeContexts . size ( ) + _reclaimedContexts . size ( ) != threads ) { report ( " " << ( _freeContexts . size ( ) + _reclaimedContexts . size ( ) ) << " " << threads << " " ) ; _computeNextFunction ( ) ; warpList = std :: move ( _queuedThreads [ _nextFunction ] ) ; const unsigned int threads = warpList . size ( ) ; const unsigned int warps = threads / _warpSize ; const unsigned int remains = threads % _warpSize ; report ( " " << _nextFunction << " " << _functions [ _nextFunction ] -> kernel -> name << " " ) ; report ( " " << threads ) ; report ( " " << warps ) ; report ( " " << remains ) ; ThreadList :: const_iterator begin = warpList . begin ( ) ; for ( unsigned int warp = 0 ; warp != warps ; ++ warp ) { ThreadList :: const_iterator end = begin ; std :: advance ( end , _warpSize ) ; _executeWarp ( begin , end ) ; begin = end ; } ThreadList :: const_iterator end = begin ; std :: advance ( end , remains ) ; _executeWarp ( begin , end ) ; for ( ThreadList :: const_iterator context = warpList . begin ( ) ; context != warpList . end ( ) ; ++ context ) { _destroyContext ( * context ) ; } warpList . clear ( ) ; } _destroyContexts ( ) ; }
We want to execute the CTA as quickly as possibly.
We want to execute the CTA as quickly as possibly .