Skip to content
Snippets Groups Projects
Select Git revision
  • 5202512a234d8902e8146fa0c985c38ddbd9ba3c
  • master default
  • ci-bump-test
  • abp-queue
  • new-delete-leaks
  • fused-continuation-and-completion-stealing
  • emper-fix-invalid-conv
  • remote-put-get-free-context-cycle
  • linux-version-construct-on-first-use
  • libstdc++-asserts
  • msan
  • libc++
  • completer-strategies
  • cactus_stack_devel_one_commit
  • client-load-change
  • cppcheck
  • flow
  • cast-if-future
  • async_network2
  • thread_safe_log_config
  • burak
  • attic/clang-release-tls-optimization-debug-and-fix
  • attic/continuation-stealing-dev
23 results

SpawnALot.cpp

Blame
  • Forked from Lehrstuhl für Informatik 4 (Systemsoftware) / manycore / emper
    Source project has a limited visibility.
    SpawnALot.cpp 4.62 KiB
    #include "Runtime.hpp"
    #include "PrivateSemaphore.hpp"
    #include "BinaryPrivateSemaphore.hpp"
    #include "CountingPrivateSemaphore.hpp"
    #include "DebugUtil.hpp"
    
    #define CACHE_LINE_SIZE 64
    
    static void spawnALotThreadsRecursiveTFun(unsigned int depth, unsigned int width, unsigned int current_depth) {
    		if (current_depth == depth) return;
    
    		std::thread* threads = new std::thread[width];
    		const unsigned int new_depth = current_depth + 1;
    		for (unsigned int i = 0; i < width; ++i) {
    			threads[i] = std::thread(spawnALotThreadsRecursiveTFun, depth, width, new_depth);
    		}
    		for (unsigned int i = 0; i < width; ++i) {
    			threads[i].join();
    		}
    
    		delete[] threads;
    }
    
    static void spawnALotThreadsRecursive(unsigned int depth, unsigned int width) {
    	std::thread thread(spawnALotThreadsRecursiveTFun, depth, width, 0);
    	thread.join();
    }
    
    static void spawnALotThreadsNonRecursive(uint64_t count) {
    	uint8_t* flags = new uint8_t[count * CACHE_LINE_SIZE];
    	std::thread* threads = new std::thread[count];
    	for (uint64_t i = 0; i < count; ++i) {
    		threads[i] = std::thread([&flags, i] {
    				flags[i * CACHE_LINE_SIZE] = 1;
    			});
    	}
    
    	for (uint64_t i = 0; i < count; ++i) {
    		threads[i].join();
    	}
    
    	delete[] flags;
    	delete[] threads;
    }
    
    struct SpawnALotFibersData {
    	Runtime& runtime;
    	const unsigned int depth;
    	const unsigned int width;
    	PS& ps;
    	unsigned int current_depth;
    
    	SpawnALotFibersData(SpawnALotFibersData* oldData, PS& ps)
    		: runtime(oldData->runtime)
    		, depth(oldData->depth)
    		, width(oldData->width)
    		, ps(ps)
    		, current_depth(oldData->current_depth + 1) {
    	}
    
    	SpawnALotFibersData(Runtime& runtime, unsigned int depth, unsigned int width, PS& ps)
    		: runtime(runtime)
    		, depth(depth)
    		, width(width)
    		, ps(ps)
    		, current_depth(0) {
    	}
    
    };
    
    static void spawnALotFibersRecursiveFFun(void* dataPtr) {
    	SpawnALotFibersData* data = (SpawnALotFibersData*) dataPtr;
    	if (data->current_depth < data->depth) {
    		CPS childSem(data->width);
    		SpawnALotFibersData newData(data, childSem);
    
    		for (unsigned int i = 0; i < data->width; ++i) {
    			Fiber* fiber = Fiber::from(spawnALotFibersRecursiveFFun, (void*) &newData);
    			data->runtime.schedule(*fiber);
    		}
    
    		childSem.wait();
    	}
    
    	data->ps.signal();
    }
    
    static void spawnALotFibersRecursive(Runtime& runtime, unsigned int depth, unsigned int width) {
    	BPS bps;
    	SpawnALotFibersData data(runtime, depth, width, bps);
    
    	Fiber* fiber = Fiber::from(spawnALotFibersRecursiveFFun, (void*) &data);
    	runtime.schedule(*fiber);
    
    	bps.wait();
    }
    
    static void spawnALotFibersNonRecursive(Runtime& runtime, uint64_t count) {
    	uint8_t* flags = new uint8_t[count * CACHE_LINE_SIZE];
    	CPS cps(count);
    
    	for (uint64_t i = 0; i < count; ++i) {
    		Fiber* fiber = Fiber::from([i, &cps, flags] {
    				flags[i * CACHE_LINE_SIZE] = 1;
    				cps.signal();
    			});
    		runtime.schedule(*fiber);
    	}
    
    	cps.wait();
    
    	delete[] flags;
    }
    
    int main(UNUSED_ARG int argc, UNUSED_ARG char *argv[]) {
    	enableStacktraceOnAborts();
    	const uint64_t count = 1024;
    
    	const unsigned int depth = 10;
    	const unsigned int width = 2;
    
    	std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
    	std::chrono::nanoseconds diff;
    
    	start = std::chrono::high_resolution_clock::now();
    	spawnALotThreadsRecursive(depth, width);
    	end = std::chrono::high_resolution_clock::now();
    	diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end -start);
    	std::cout << "Spawn a lot of threads recursive (depth="
    			  << depth << ", width="
    			  << width << ") took "
    			  << diff.count() << "us"
    			  << std::endl;
    
    	start = std::chrono::high_resolution_clock::now();
    	spawnALotThreadsNonRecursive(count);
    	end = std::chrono::high_resolution_clock::now();
    	diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end -start);
    	std::cout << "Spawn a lot of threads non-recursive (count="
    			  << count << ") took "
    			  << diff.count() << "us"
    			  << std::endl;
    
    	Runtime runtime;
    
    	runtime.executeAndWait([&] {
    			start = std::chrono::high_resolution_clock::now();
    			spawnALotFibersRecursive(runtime, depth, width);
    			end = std::chrono::high_resolution_clock::now();
    			diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end -start);
    			std::cout << "Spawn a lot of fibers recursive (depth="
    					  << depth << ", width="
    					  << width << ") took "
    					  << diff.count() << "us"
    					  << std::endl;
    
    			start = std::chrono::high_resolution_clock::now();
    			spawnALotFibersNonRecursive(runtime, count);
    			end = std::chrono::high_resolution_clock::now();
    			diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end -start);
    			std::cout << "Spawn a lot of fibers non-recursive (count="
    					  << count << ") took "
    					  << diff.count() << "us"
    					  << std::endl;
    		});
    
    	return EXIT_SUCCESS;
    }