├── .github
└── FUNDING.yml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── License.txt
├── README.md
├── enkiTSMicroprofileExample.cpp
├── enkiTSRemoteryExample.c
├── enkiTSRemoteryExample.cpp
└── images
├── enkiTSMicroprofileExample.png
└── enkiTSRemoteryExample.png
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: dougbinks
4 | patreon: enkisoftware
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: https://www.enkisoftware.com/avoyd
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | .vscode
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "enkiTS"]
2 | path = enkiTS
3 | url = https://github.com/dougbinks/enkiTS
4 | [submodule "Remotery"]
5 | path = Remotery
6 | url = https://github.com/Celtoys/Remotery
7 | [submodule "microprofile"]
8 | path = microprofile
9 | url = https://github.com/dougbinks/microprofile
10 | [submodule "imgui"]
11 | path = imgui
12 | url = https://github.com/ocornut/imgui
13 | [submodule "glfw"]
14 | path = glfw
15 | url = https://github.com/glfw/glfw.git
16 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 |
3 | project( enkiTSExamples )
4 |
5 | find_package(OpenGL)
6 |
7 | include_directories("enkiTS/src")
8 | include_directories("Remotery/lib")
9 | include_directories("imgui")
10 | include_directories("microprofile")
11 | include_directories("glfw/include")
12 | include_directories("imgui/examples")
13 | include_directories( ${OPENGL_INCLUDE_DIRS} )
14 |
15 | set( ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build basic example applications" )
16 | set( GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW lib only" )
17 | set( GLFW_BUILD_TESTS OFF CACHE BOOL "GLFW lib only" )
18 | set( GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW lib only" )
19 | set( GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" )
20 |
21 | add_subdirectory( enkiTS )
22 |
23 | if(OpenGL_FOUND)
24 | add_subdirectory( glfw )
25 | endif()
26 |
27 | set( ENKITSREMOTERYSAMPLE_SRC
28 | enkiTSRemoteryExample.cpp
29 | Remotery/lib/Remotery.h
30 | Remotery/lib/Remotery.c
31 | )
32 |
33 | add_executable( enkiTSRemoteryExample ${ENKITSREMOTERYSAMPLE_SRC} )
34 | target_link_libraries(enkiTSRemoteryExample enkiTS )
35 |
36 | if( ENKITS_BUILD_C_INTERFACE )
37 | set( ENKITSREMOTERYSAMPLE_C_SRC
38 | enkiTSRemoteryExample.c
39 | Remotery/lib/Remotery.h
40 | Remotery/lib/Remotery.c
41 | )
42 | add_executable( enkiTSRemoteryExample_C ${ENKITSREMOTERYSAMPLE_C_SRC} )
43 | target_link_libraries(enkiTSRemoteryExample_C enkiTS )
44 | endif()
45 |
46 | if(UNIX)
47 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
48 | endif()
49 | if(APPLE)
50 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
51 | endif()
52 | if( MSVC )
53 | SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup" )
54 | endif()
55 |
56 | if(OpenGL_FOUND)
57 | set( ENKITSMICROPROFILESAMPLE_SRC
58 | microprofile/microprofile.h
59 | microprofile/microprofileui.h
60 | imgui/imgui.h
61 | imgui/imgui.cpp
62 | imgui/imgui_internal.h
63 | imgui/imgui_demo.cpp
64 | imgui/imgui_draw.cpp
65 | imgui/imgui_widgets.cpp
66 | imgui/imconfig.h
67 | imgui/examples/imgui_impl_glfw.h
68 | imgui/examples/imgui_impl_glfw.cpp
69 | imgui/examples/imgui_impl_opengl2.h
70 | imgui/examples/imgui_impl_opengl2.cpp
71 | enkiTSMicroprofileExample.cpp
72 | )
73 | add_executable( enkiTSMicroprofileExample WIN32 ${ENKITSMICROPROFILESAMPLE_SRC} )
74 | target_link_libraries(enkiTSMicroprofileExample enkiTS ${OPENGL_LIBRARIES} glfw ${GLFW_LIBRARIES} )
75 | endif()
76 |
77 | if( MSVC )
78 | if(${CMAKE_VERSION} VERSION_LESS "3.6.0")
79 | message( "\n\t[ WARNING ]\n\n\tCMake version lower than 3.6.\n\n\t - Please update CMake and rerun; OR\n\t - Manually set one of the 'Example' projects as StartUp Project in Visual Studio.\n" )
80 | else()
81 | set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT enkiTSMicroprofileExample )
82 | endif()
83 | endif()
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Doug Binks
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgement in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Support development of enkiTS through [Github Sponsors](https://github.com/sponsors/dougbinks) or [Patreon](https://www.patreon.com/enkisoftware)
2 |
3 | [
](https://github.com/sponsors/dougbinks) [
](https://www.patreon.com/enkisoftware)
4 |
5 | 
6 | # [enkiTS](https://github.com/dougbinks/enkiTS/) Examples
7 |
8 | **Submodules are licensed under their own licenses, see their contents for details**
9 |
10 | ## Building
11 |
12 | First [make sure you've cloned all submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules#Cloning-a-Project-with-Submodules). On Windows / Mac OS X / Linux with cmake installed, open a prompt in the enkiTS directory and:
13 |
14 | 1. `mkdir build`
15 | 2. `cmake ..`
16 | 3. either run `make` or on Windows with Visual Studio open `enkiTSExamples.sln`
17 |
18 | ## enki Task Scheduler Extended Samples
19 |
20 | [enkiTS](https://github.com/dougbinks/enkiTS/) is a permissively licensed C and C++ Task Scheduler for creating parallel programs.
21 |
22 | This repository hosts extended examples.
23 |
24 | ## [enkiTSRemoteryExample.cpp](enkiTSRemoteryExample.cpp)
25 |
26 | This example shows how to use [Remotery](https://github.com/Celtoys/Remotery) with [enkiTS](https://github.com/dougbinks/enkiTS/).
27 |
28 | Note that currently in release the sums might be optimized away.
29 |
30 | 
31 |
32 | ## [enkiTSRemoteryExample.c](enkiTSRemoteryExample.c)
33 |
34 | As above but using the C interface.
35 |
36 | ## [enkiTSMicroprofileExample.cpp](enkiTSMicroprofileExample.cpp)
37 |
38 | This example shows how to use [microprofile](https://github.com/dougbinks/microprofile) with [enkiTS](https://github.com/dougbinks/enkiTS/).
39 |
40 | To view context switching on Windows, run the application (or Visual Studio if launching from that) as administrator and set Options->Cswitch Trace->Enable on.
41 |
42 | 
43 |
44 | ## License (zlib)
45 |
46 | Copyright (c) 2013 Doug Binks
47 |
48 | This software is provided 'as-is', without any express or implied
49 | warranty. In no event will the authors be held liable for any damages
50 | arising from the use of this software.
51 |
52 | Permission is granted to anyone to use this software for any purpose,
53 | including commercial applications, and to alter it and redistribute it
54 | freely, subject to the following restrictions:
55 |
56 | 1. The origin of this software must not be misrepresented; you must not
57 | claim that you wrote the original software. If you use this software
58 | in a product, an acknowledgement in the product documentation would be
59 | appreciated but is not required.
60 | 2. Altered source versions must be plainly marked as such, and must not be
61 | misrepresented as being the original software.
62 | 3. This notice may not be removed or altered from any source distribution.
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/enkiTSMicroprofileExample.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 Doug Binks
2 | //
3 | // This software is provided 'as-is', without any express or implied
4 | // warranty. In no event will the authors be held liable for any damages
5 | // arising from the use of this software.
6 | //
7 | // Permission is granted to anyone to use this software for any purpose,
8 | // including commercial applications, and to alter it and redistribute it
9 | // freely, subject to the following restrictions:
10 | //
11 | // 1. The origin of this software must not be misrepresented; you must not
12 | // claim that you wrote the original software. If you use this software
13 | // in a product, an acknowledgement in the product documentation would be
14 | // appreciated but is not required.
15 | // 2. Altered source versions must be plainly marked as such, and must not be
16 | // misrepresented as being the original software.
17 | // 3. This notice may not be removed or altered from any source distribution.
18 |
19 | #ifdef _WIN32
20 | #pragma warning(disable:4996)
21 | #endif
22 | #define MICROPROFILE_IMPL
23 | #define MICROPROFILEUI_IMPL
24 | #define MICROPROFILE_WEBSERVER 0
25 | #define MICROPROFILE_TEXT_HEIGHT 12
26 | #define MICROPROFILE_TEXT_WIDTH 7
27 | #define MICROPROFILE_GPU_TIMERS 0
28 | #define NOMINMAX
29 | #include "microprofile.h"
30 | #include "microprofileui.h"
31 |
32 | #include "TaskScheduler.h"
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 |
42 | #include
43 | #include "imgui_impl_glfw.h"
44 | #include "imgui_impl_opengl2.h"
45 | #include
46 |
47 | static const int MINRANGE = 10 * 1024;
48 | static const int SUMS = 10*1024*1024;
49 |
50 | // UI functions
51 | static ImDrawList* g_pImDraw = 0;
52 | static ImVec2 g_DrawStart;
53 | static ImVec2 g_DrawSize;
54 |
55 | void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, uint32_t nNumCharacters)
56 | {
57 | g_pImDraw->AddText( ImVec2(nX + g_DrawStart.x,nY + g_DrawStart.y ), nColor, pText, pText + nNumCharacters );
58 | }
59 |
60 | inline bool IsBoxInside( ImVec2 p0, ImVec2 p1 )
61 | {
62 | return ( p1.x >= g_DrawStart.x && p0.x < g_DrawStart.x + g_DrawSize.x ) && ( p1.y >= g_DrawStart.y && p0.y < g_DrawStart.y + g_DrawSize.y );
63 | }
64 |
65 | void MicroProfileDrawBox(int nX, int nY, int nX1, int nY1, uint32_t nColor, MicroProfileBoxType boxType )
66 | {
67 | ImVec2 p0(nX + g_DrawStart.x,nY + g_DrawStart.y );
68 | ImVec2 p1(nX1 + g_DrawStart.x,nY1 + g_DrawStart.y );
69 | if( !IsBoxInside(p0,p1))
70 | {
71 | return;
72 | }
73 |
74 | switch( boxType )
75 | {
76 | case MicroProfileBoxTypeBar:
77 | {
78 | uint32_t cul = nColor;
79 | uint32_t cur = ( nColor & 0x00FFFFFF ) + 0xFF000000;
80 | uint32_t clr = ( nColor & 0x00FFFFFF ) + 0x50000000;
81 | uint32_t cll = ( nColor & 0x00FFFFFF ) + 0x50000000;
82 | g_pImDraw->AddRectFilledMultiColor(p0, p1, cul, cur, clr, cll );
83 | if( nX1 - nX > 5 )
84 | {
85 | g_pImDraw->AddRect(p0, p1, 0x50000000 );
86 | }
87 | break;
88 | }
89 | case MicroProfileBoxTypeFlat:
90 | g_pImDraw->AddRectFilled(p0, p1, nColor );
91 | break;
92 | default:
93 | assert(false);
94 | }
95 | }
96 |
97 | void MicroProfileDrawLine2D(uint32_t nVertices, float* pVertices, uint32_t nColor)
98 | {
99 | for( uint32_t vert = 0; vert + 1 < nVertices; ++vert )
100 | {
101 | uint32_t i = 2*vert;
102 | ImVec2 posA( pVertices[i] + g_DrawStart.x, pVertices[i+1] + g_DrawStart.y );
103 | ImVec2 posB( pVertices[i+2] + g_DrawStart.x, pVertices[i+3] + g_DrawStart.y );
104 | g_pImDraw->AddLine( posA, posB, nColor );
105 | }
106 | }
107 |
108 | static void error_callback(int error, const char* description)
109 | {
110 | fprintf(stderr, "Error %d: %s\n", error, description);
111 | }
112 |
113 |
114 | using namespace enki;
115 |
116 |
117 | TaskScheduler g_TS;
118 |
119 |
120 | struct ParallelSumTaskSet : ITaskSet
121 | {
122 | struct Count
123 | {
124 | // prevent false sharing.
125 | uint64_t count;
126 | char cacheline[64];
127 | };
128 | Count* m_pPartialSums;
129 | uint32_t m_NumPartialSums;
130 |
131 | ParallelSumTaskSet( uint32_t size_ ) : m_pPartialSums(NULL), m_NumPartialSums(0) { m_SetSize = size_; m_MinRange = MINRANGE; }
132 | virtual ~ParallelSumTaskSet()
133 | {
134 | delete[] m_pPartialSums;
135 | }
136 |
137 | void Init()
138 | {
139 | MICROPROFILE_SCOPEI("Parallel", "SumInit", 0xFF008800 );
140 | delete[] m_pPartialSums;
141 | m_NumPartialSums = g_TS.GetNumTaskThreads();
142 | m_pPartialSums = new Count[ m_NumPartialSums ];
143 | memset( m_pPartialSums, 0, sizeof(Count)*m_NumPartialSums );
144 | }
145 |
146 | virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum )
147 | {
148 | MICROPROFILE_SCOPEI("Parallel", "SumTask", 0xFF00D000 );
149 | assert( m_pPartialSums && m_NumPartialSums );
150 | uint64_t sum = m_pPartialSums[threadnum].count;
151 | for( uint64_t i = range.start; i < range.end; ++i )
152 | {
153 | sum += i + 1;
154 | }
155 | m_pPartialSums[threadnum].count = sum;
156 | }
157 |
158 | };
159 |
160 | struct ParallelReductionSumTaskSet : ITaskSet
161 | {
162 | ParallelSumTaskSet m_ParallelSumTaskSet;
163 | uint64_t m_FinalSum;
164 |
165 | ParallelReductionSumTaskSet( uint32_t size_ ) : m_ParallelSumTaskSet( size_ ), m_FinalSum(0) {}
166 |
167 | void Init()
168 | {
169 | m_ParallelSumTaskSet.Init();
170 | }
171 |
172 | virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum )
173 | {
174 | MICROPROFILE_SCOPEI("Parallel", "ReductionTask", 0xFF20C000 );
175 | g_TS.AddTaskSetToPipe( &m_ParallelSumTaskSet );
176 | g_TS.WaitforTask( &m_ParallelSumTaskSet );
177 |
178 | for( uint32_t i = 0; i < m_ParallelSumTaskSet.m_NumPartialSums; ++i )
179 | {
180 | m_FinalSum += m_ParallelSumTaskSet.m_pPartialSums[i].count;
181 | }
182 | }
183 | };
184 |
185 | void threadStartCallback( uint32_t threadnum_ )
186 | {
187 | std::ostringstream out;
188 | out << "enkiTS_" << threadnum_;
189 | MicroProfileOnThreadCreate( out.str().c_str() );
190 | }
191 |
192 | // tickstore implements a stack the same size as Microprofiles, but continues to function
193 | // without reporting timings for deeper stacks
194 | struct TickStore
195 | {
196 | uint64_t tickStack[MICROPROFILE_STACK_MAX] = {0};
197 | int32_t tickStackNext = 0;
198 |
199 | void ProfileEnter( MicroProfileToken token_ ) {
200 | if( tickStackNext < MICROPROFILE_STACK_MAX ) {
201 | tickStack[ tickStackNext ] = MicroProfileEnter( token_ );
202 | }
203 | ++tickStackNext;
204 | }
205 |
206 | void ProfileLeave( MicroProfileToken token_ ) {
207 | assert( tickStackNext > 0 ); // unmatched enter/leave
208 | --tickStackNext;
209 | if( tickStackNext < MICROPROFILE_STACK_MAX ) {
210 | MicroProfileLeave( token_, tickStack[ tickStackNext ] );
211 | }
212 | }
213 | };
214 |
215 | static TickStore* g_pTicks = NULL;
216 |
217 | void profilerInit() {
218 | g_pTicks = new TickStore[ enki::GetNumHardwareThreads() ];
219 | }
220 |
221 | MicroProfileToken g_ProfileWaitForNewTaskSuspend = MicroProfileGetToken( "enkiTS", "waitForNewTaskSuspend", 0xFF505000, MicroProfileTokenTypeCpu);
222 | void waitForNewTaskSuspendStartCallback( uint32_t threadnum_ ) {
223 | g_pTicks[ threadnum_ ].ProfileEnter( g_ProfileWaitForNewTaskSuspend );
224 | }
225 |
226 | void waitForNewTaskSuspendStopCallback( uint32_t threadnum_ ) {
227 | g_pTicks[ threadnum_ ].ProfileLeave( g_ProfileWaitForNewTaskSuspend );
228 | }
229 |
230 | MicroProfileToken g_ProfileWaitForTaskComplete = MicroProfileGetToken( "enkiTS", "waitForTaskComplete", 0xFF005050, MicroProfileTokenTypeCpu);
231 | void waitForTaskCompleteStartCallback( uint32_t threadnum_ ) {
232 |
233 | g_pTicks[ threadnum_ ].ProfileEnter( g_ProfileWaitForTaskComplete );
234 | }
235 |
236 | void waitForTaskCompleteStopCallback( uint32_t threadnum_ ) {
237 | g_pTicks[ threadnum_ ].ProfileLeave( g_ProfileWaitForTaskComplete );
238 | }
239 |
240 | MicroProfileToken g_ProfileWaitForTaskCompleteSuspend = MicroProfileGetToken( "enkiTS", "waitForTaskCompleteSuspend", 0xFF005090, MicroProfileTokenTypeCpu);
241 | void waitForTaskCompleteSuspendStartCallback( uint32_t threadnum_ ) {
242 | g_pTicks[ threadnum_ ].ProfileEnter( g_ProfileWaitForTaskCompleteSuspend );
243 | }
244 |
245 | void waitForTaskCompleteSuspendStopCallback( uint32_t threadnum_ ) {
246 | g_pTicks[ threadnum_ ].ProfileLeave( g_ProfileWaitForTaskCompleteSuspend );
247 | }
248 |
249 | int main(int argc, const char * argv[])
250 | {
251 | // Setup window
252 | glfwSetErrorCallback(error_callback);
253 | if (!glfwInit())
254 | exit(1);
255 | GLFWwindow* window = glfwCreateWindow(1280, 720, "enkiTS microprofile example", NULL, NULL);
256 | glfwMakeContextCurrent(window);
257 | glfwSwapInterval(1); // Enable vsync
258 |
259 | // Setup Dear ImGui binding
260 | IMGUI_CHECKVERSION();
261 | ImGui::CreateContext();
262 |
263 | ImGui_ImplGlfw_InitForOpenGL(window, true);
264 | ImGui_ImplOpenGL2_Init();
265 |
266 | // Setup style
267 | ImGui::StyleColorsDark();
268 |
269 |
270 | // Set up Microprofile
271 | MicroProfileToggleDisplayMode();
272 | MicroProfileInitUI();
273 | MicroProfileOnThreadCreate("Main");
274 |
275 | // setup profile default settings
276 | MicroProfile& profiler = *MicroProfileGet();
277 | profiler.nDisplay = MP_DRAW_DETAILED;
278 | profiler.nAllGroupsWanted = 1;
279 |
280 | enki::TaskSchedulerConfig tsConfig;
281 | tsConfig.profilerCallbacks.threadStart = threadStartCallback;
282 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStart = waitForNewTaskSuspendStartCallback;
283 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStop = waitForNewTaskSuspendStopCallback;
284 | tsConfig.profilerCallbacks.waitForTaskCompleteStart = waitForTaskCompleteStartCallback;
285 | tsConfig.profilerCallbacks.waitForTaskCompleteStop = waitForTaskCompleteStopCallback;
286 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStart = waitForTaskCompleteSuspendStartCallback;
287 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStop = waitForTaskCompleteSuspendStopCallback;
288 |
289 | profilerInit();
290 | g_TS.Initialize( tsConfig );
291 |
292 | double avSpeedUp = 0.0;
293 | ImVec4 clear_color = ImColor(114, 144, 154);
294 | while (!glfwWindowShouldClose(window))
295 | {
296 | MICROPROFILE_SCOPEI("MainThread", "MainLoop", 0xFF555555 );
297 | glfwPollEvents();
298 |
299 | // Start the Dear ImGui frame
300 | ImGui_ImplOpenGL2_NewFrame();
301 | ImGui_ImplGlfw_NewFrame();
302 | ImGui::NewFrame();
303 |
304 |
305 | ParallelReductionSumTaskSet m_ParallelReductionSumTaskSet( SUMS );
306 | {
307 | MICROPROFILE_SCOPEI("MainThread", "LaunchAndRunParallel", 0xFF555555 );
308 |
309 | m_ParallelReductionSumTaskSet.Init();
310 |
311 | g_TS.AddTaskSetToPipe(&m_ParallelReductionSumTaskSet);
312 |
313 | g_TS.WaitforTask(&m_ParallelReductionSumTaskSet);
314 | }
315 |
316 |
317 |
318 | volatile uint64_t sum = 0;
319 | {
320 | MICROPROFILE_SCOPEI("Serial", "Sum", 0xFF0000D0 );
321 | for (uint64_t i = 0; i < (uint64_t)m_ParallelReductionSumTaskSet.m_ParallelSumTaskSet.m_SetSize; ++i)
322 | {
323 | sum += i + 1;
324 | }
325 | }
326 |
327 | if(true)
328 | {
329 | MicroProfileFlip(NULL);
330 | ImGui::SetNextWindowSize(ImVec2(1200,700), ImGuiCond_FirstUseEver);
331 | ImGui::SetNextWindowPos(ImVec2(10,10), ImGuiCond_FirstUseEver);
332 | ImGui::Begin( "Microprofile" );
333 |
334 | g_pImDraw = ImGui::GetWindowDrawList();
335 | g_DrawStart = ImGui::GetCursorScreenPos();
336 | g_DrawSize = ImGui::GetContentRegionAvail();
337 |
338 | ImGui::InvisibleButton("canvas", g_DrawSize);
339 | if (ImGui::IsItemHovered())
340 | {
341 | MicroProfileMouseButton( ImGui::GetIO().MouseDown[0], ImGui::GetIO().MouseDown[1] );
342 | }
343 | else
344 | {
345 | MicroProfileMouseButton( 0, 0 );
346 | }
347 | MicroProfileMousePosition((uint32_t)(ImGui::GetIO().MousePos.x- g_DrawStart.x), (uint32_t)(ImGui::GetIO().MousePos.y - g_DrawStart.y), (int)ImGui::GetIO().MouseWheel );
348 | MicroProfileDraw((uint32_t)g_DrawSize.x, (uint32_t)g_DrawSize.y);
349 |
350 | ImGui::End();
351 | }
352 |
353 | // Rendering
354 | {
355 | MICROPROFILE_SCOPEI("MainThread", "Render", 0xFF882222 );
356 | glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
357 | glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
358 | glClear(GL_COLOR_BUFFER_BIT);
359 | ImGui::Render();
360 | ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
361 | glfwSwapBuffers(window);
362 | }
363 | }
364 |
365 |
366 | // Cleanup
367 | g_TS.WaitforAllAndShutdown();
368 | ImGui_ImplOpenGL2_Shutdown();
369 | ImGui_ImplGlfw_Shutdown();
370 | ImGui::DestroyContext();
371 | glfwTerminate();
372 |
373 | return 0;
374 | }
375 |
--------------------------------------------------------------------------------
/enkiTSRemoteryExample.c:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 Doug Binks
2 | //
3 | // This software is provided 'as-is', without any express or implied
4 | // warranty. In no event will the authors be held liable for any damages
5 | // arising from the use of this software.
6 | //
7 | // Permission is granted to anyone to use this software for any purpose,
8 | // including commercial applications, and to alter it and redistribute it
9 | // freely, subject to the following restrictions:
10 | //
11 | // 1. The origin of this software must not be misrepresented; you must not
12 | // claim that you wrote the original software. If you use this software
13 | // in a product, an acknowledgement in the product documentation would be
14 | // appreciated but is not required.
15 | // 2. Altered source versions must be plainly marked as such, and must not be
16 | // misrepresented as being the original software.
17 | // 3. This notice may not be removed or altered from any source distribution.
18 |
19 | #include "TaskScheduler_c.h"
20 | #include
21 | #include
22 | #include
23 |
24 | #include "Remotery.h"
25 |
26 | enkiTaskScheduler* pETS;
27 | enkiTaskSet* pPSumTask;
28 | enkiTaskSet* pPSumReductionTask;
29 |
30 | static const int RUNS = 1024 * 1024;
31 | static const int MINRANGE = 10 * 1024;
32 | static const int SUMS = 10 * 1024 * 1024;
33 |
34 |
35 | typedef struct ParallelSumTaskSetArgs
36 | {
37 | uint64_t* pPartialSums;
38 | uint32_t numPartialSums;
39 | } ParallelSumTaskSetArgs;
40 |
41 | void ParallelSumTaskSetArgsInit( ParallelSumTaskSetArgs* pArgs_ )
42 | {
43 | pArgs_->numPartialSums = enkiGetNumTaskThreads( pETS );
44 | pArgs_->pPartialSums = (uint64_t*)malloc( sizeof(uint64_t) * pArgs_->numPartialSums );
45 | memset( pArgs_->pPartialSums, 0, sizeof(uint64_t) * pArgs_->numPartialSums );
46 | }
47 |
48 | void ParallelSumTaskSetFunc( uint32_t start_, uint32_t end, uint32_t threadnum_, void* pArgs_ )
49 | {
50 | rmt_BeginCPUSample(Sum, 0);
51 |
52 | ParallelSumTaskSetArgs args;
53 | uint64_t sum, i;
54 |
55 | args = *(ParallelSumTaskSetArgs*)pArgs_;
56 |
57 | sum = args.pPartialSums[threadnum_];
58 | for( i = start_; i < end; ++i )
59 | {
60 | sum += i + 1;
61 | }
62 | args.pPartialSums[threadnum_] = sum;
63 |
64 | rmt_EndCPUSample();
65 | }
66 |
67 | void ParallelReductionSumTaskSet( uint32_t start_, uint32_t end, uint32_t threadnum_, void* pArgs_ )
68 | {
69 | rmt_BeginCPUSample(Reduce, 0);
70 |
71 | ParallelSumTaskSetArgs args;
72 | uint64_t sum;
73 | uint64_t inMax_outSum, i;
74 |
75 | inMax_outSum = *(uint64_t*)pArgs_;
76 |
77 | ParallelSumTaskSetArgsInit( &args );
78 |
79 | enkiAddTaskSetMinRange( pETS, pPSumTask, &args, (uint32_t)inMax_outSum, MINRANGE );
80 | enkiWaitForTaskSet( pETS, pPSumTask );
81 |
82 | sum = 0;
83 | for( i = 0; i < args.numPartialSums; ++i )
84 | {
85 | sum += args.pPartialSums[i];
86 | }
87 |
88 | free( args.pPartialSums );
89 |
90 | *(uint64_t*)pArgs_ = sum;
91 |
92 | rmt_EndCPUSample();
93 | }
94 |
95 |
96 | static char* nameTable[] = {
97 | "enkiTS_00", "enkiTS_01", "enkiTS_02", "enkiTS_03", "enkiTS_04", "enkiTS_05", "enkiTS_06", "enkiTS_07", "enkiTS_08", "enkiTS_09",
98 | "enkiTS_10", "enkiTS_11", "enkiTS_12", "enkiTS_13", "enkiTS_14", "enkiTS_15", "enkiTS_16", "enkiTS_17", "enkiTS_18", "enkiTS_19",
99 | "enkiTS_20", "enkiTS_21", "enkiTS_22", "enkiTS_23", "enkiTS_24", "enkiTS_25", "enkiTS_26", "enkiTS_27", "enkiTS_28", "enkiTS_29",
100 | "enkiTS_30", "enkiTS_31", "enkiTS_32", "enkiTS_33", "enkiTS_34", "enkiTS_35", "enkiTS_36", "enkiTS_37", "enkiTS_38", "enkiTS_39",
101 | "enkiTS_40", "enkiTS_41", "enkiTS_42", "enkiTS_43", "enkiTS_44", "enkiTS_45", "enkiTS_46", "enkiTS_47", "enkiTS_48", "enkiTS_49",
102 | "enkiTS_50", "enkiTS_51", "enkiTS_52", "enkiTS_53", "enkiTS_54", "enkiTS_55", "enkiTS_56", "enkiTS_57", "enkiTS_58", "enkiTS_59",
103 | "enkiTS_60", "enkiTS_61", "enkiTS_62", "enkiTS_63", "enkiTS_64", "enkiTS_XX",
104 | };
105 | const uint32_t nameTableSize = (uint32_t)sizeof( nameTable ) / sizeof( const char* );
106 |
107 | void threadStartCallback( uint32_t threadnum_ )
108 | {
109 | uint32_t nameNum = threadnum_;
110 | if( nameNum >= nameTableSize ) { nameNum = nameTableSize-1; }
111 | rmt_SetCurrentThreadName( nameTable[ nameNum ] );
112 | }
113 |
114 | void waitForNewTaskSuspendStartCallback( uint32_t threadnum_ )
115 | {
116 | rmt_BeginCPUSample(WaitForNewTaskSuspend, 0);
117 | }
118 |
119 | void waitForTaskCompleteStartCallback( uint32_t threadnum_ )
120 | {
121 | rmt_BeginCPUSample(WaitForTaskComplete, 0);
122 | }
123 |
124 | void waitForTaskCompleteSuspendStartCallback( uint32_t threadnum_ )
125 | {
126 | rmt_BeginCPUSample(WaitForTaskCompleteSuspend, 0);
127 | }
128 |
129 | void stopCallback( uint32_t threadnum_ )
130 | {
131 | rmt_EndCPUSample();
132 | }
133 |
134 | int main(int argc, const char * argv[])
135 | {
136 | int run;
137 | uint64_t inMax_outSum, i;
138 | volatile uint64_t serialSum;
139 | Remotery* rmt;
140 |
141 | // the example generates a lot of samples, so increase update rate for profiler
142 | rmt_Settings()->maxNbMessagesPerUpdate = 128 * rmt_Settings()->maxNbMessagesPerUpdate;
143 | rmt_CreateGlobalInstance(&rmt);
144 |
145 | pETS = enkiNewTaskScheduler();
146 | struct enkiTaskSchedulerConfig tsConfig = enkiGetTaskSchedulerConfig( pETS );
147 |
148 | tsConfig.profilerCallbacks.threadStart = threadStartCallback;
149 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStart = waitForNewTaskSuspendStartCallback;
150 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStop = stopCallback;
151 | tsConfig.profilerCallbacks.waitForTaskCompleteStart = waitForTaskCompleteStartCallback;
152 | tsConfig.profilerCallbacks.waitForTaskCompleteStop = stopCallback;
153 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStart = waitForTaskCompleteSuspendStartCallback;
154 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStop = stopCallback;
155 |
156 | enkiInitTaskSchedulerWithConfig( pETS, tsConfig );
157 |
158 | rmt_SetCurrentThreadName("Main");
159 |
160 | pPSumTask = enkiCreateTaskSet( pETS, ParallelSumTaskSetFunc );
161 | pPSumReductionTask = enkiCreateTaskSet( pETS, ParallelReductionSumTaskSet );
162 |
163 | for (run = 0; run < RUNS; ++run)
164 | {
165 | rmt_BeginCPUSample(Run, 0);
166 |
167 | printf("Run %d\t Open Remotery\\vis\\index.html to view profiler\n", run);
168 |
169 | rmt_BeginCPUSample(Parallel, 0);
170 | inMax_outSum = SUMS;
171 | enkiAddTaskSetArgs(pETS, pPSumReductionTask, &inMax_outSum, 1);
172 | enkiWaitForTaskSet(pETS, pPSumReductionTask);
173 | rmt_EndCPUSample();
174 |
175 |
176 | rmt_BeginCPUSample(Serial, 0);
177 | serialSum = 0;
178 | for (i = 0; i < SUMS; ++i)
179 | {
180 | serialSum += i + 1;
181 | }
182 | if( inMax_outSum == serialSum )
183 | {
184 | printf("Sums Correct.\n");
185 | }
186 | else
187 | {
188 | printf("Sums ERROR.\n");
189 | }
190 |
191 | rmt_EndCPUSample();
192 |
193 | rmt_EndCPUSample();
194 | }
195 |
196 | enkiDeleteTaskScheduler( pETS );
197 | }
--------------------------------------------------------------------------------
/enkiTSRemoteryExample.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 Doug Binks
2 | //
3 | // This software is provided 'as-is', without any express or implied
4 | // warranty. In no event will the authors be held liable for any damages
5 | // arising from the use of this software.
6 | //
7 | // Permission is granted to anyone to use this software for any purpose,
8 | // including commercial applications, and to alter it and redistribute it
9 | // freely, subject to the following restrictions:
10 | //
11 | // 1. The origin of this software must not be misrepresented; you must not
12 | // claim that you wrote the original software. If you use this software
13 | // in a product, an acknowledgement in the product documentation would be
14 | // appreciated but is not required.
15 | // 2. Altered source versions must be plainly marked as such, and must not be
16 | // misrepresented as being the original software.
17 | // 3. This notice may not be removed or altered from any source distribution.
18 |
19 | #include "TaskScheduler.h"
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "Remotery.h"
28 |
29 | using namespace enki;
30 |
31 | TaskScheduler g_TS;
32 |
33 | static const int RUNS = 1024*1024;
34 | static const int MINRANGE = 10 * 1024;
35 | static const int SUMS = 10*1024*1024;
36 |
37 |
38 | struct ParallelSumTaskSet : ITaskSet
39 | {
40 | struct Count
41 | {
42 | // prevent false sharing.
43 | uint64_t count;
44 | char cacheline[64];
45 | };
46 | Count* m_pPartialSums;
47 | uint32_t m_NumPartialSums;
48 |
49 | ParallelSumTaskSet( uint32_t size_ ) : m_pPartialSums(NULL), m_NumPartialSums(0) { m_SetSize = size_; m_MinRange = MINRANGE; }
50 | virtual ~ParallelSumTaskSet()
51 | {
52 | delete[] m_pPartialSums;
53 | }
54 |
55 | void Init()
56 | {
57 | delete[] m_pPartialSums;
58 | m_NumPartialSums = g_TS.GetNumTaskThreads();
59 | m_pPartialSums = new Count[ m_NumPartialSums ];
60 | memset( m_pPartialSums, 0, sizeof(Count)*m_NumPartialSums );
61 | }
62 |
63 | virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum )
64 | {
65 | rmt_ScopedCPUSample(Sum, 0);
66 | assert( m_pPartialSums && m_NumPartialSums );
67 | uint64_t sum = m_pPartialSums[threadnum].count;
68 | for( uint64_t i = range.start; i < range.end; ++i )
69 | {
70 | sum += i + 1;
71 | }
72 | m_pPartialSums[threadnum].count = sum;
73 | }
74 |
75 | };
76 |
77 | struct ParallelReductionSumTaskSet : ITaskSet
78 | {
79 | ParallelSumTaskSet m_ParallelSumTaskSet;
80 | uint64_t m_FinalSum;
81 |
82 | ParallelReductionSumTaskSet( uint32_t size_ ) : m_ParallelSumTaskSet( size_ ), m_FinalSum(0) {}
83 |
84 | void Init()
85 | {
86 | m_ParallelSumTaskSet.Init();
87 | }
88 |
89 | virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum )
90 | {
91 | rmt_ScopedCPUSample(Reduce, 0);
92 |
93 | g_TS.AddTaskSetToPipe( &m_ParallelSumTaskSet );
94 | g_TS.WaitforTask( &m_ParallelSumTaskSet );
95 |
96 | for( uint32_t i = 0; i < m_ParallelSumTaskSet.m_NumPartialSums; ++i )
97 | {
98 | m_FinalSum += m_ParallelSumTaskSet.m_pPartialSums[i].count;
99 | }
100 | }
101 | };
102 |
103 | void threadStartCallback( uint32_t threadnum_ )
104 | {
105 | std::ostringstream out;
106 | out << "enkiTS_" << threadnum_;
107 | rmt_SetCurrentThreadName( out.str().c_str() );
108 | }
109 |
110 | void waitForNewTaskSuspendStartCallback( uint32_t threadnum_ )
111 | {
112 | rmt_BeginCPUSample(WaitForNewTaskSuspend, 0);
113 | }
114 |
115 | void waitForTaskCompleteStartCallback( uint32_t threadnum_ )
116 | {
117 | rmt_BeginCPUSample(WaitForTaskComplete, 0);
118 | }
119 |
120 | void waitForTaskCompleteSuspendStartCallback( uint32_t threadnum_ )
121 | {
122 | rmt_BeginCPUSample(WaitForTaskCompleteSuspend, 0);
123 | }
124 |
125 | void stopCallback( uint32_t threadnum_ )
126 | {
127 | rmt_EndCPUSample();
128 | }
129 |
130 | int main(int argc, const char * argv[])
131 | {
132 | // the example generates a lot of samples, so increase update rate for profiler
133 | rmt_Settings()->maxNbMessagesPerUpdate = 128 * rmt_Settings()->maxNbMessagesPerUpdate;
134 |
135 | Remotery* rmt;
136 | rmt_CreateGlobalInstance(&rmt);
137 |
138 | enki::TaskSchedulerConfig tsConfig;
139 | tsConfig.profilerCallbacks.threadStart = threadStartCallback;
140 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStart = waitForNewTaskSuspendStartCallback;
141 | tsConfig.profilerCallbacks.waitForNewTaskSuspendStop = stopCallback;
142 | tsConfig.profilerCallbacks.waitForTaskCompleteStart = waitForTaskCompleteStartCallback;
143 | tsConfig.profilerCallbacks.waitForTaskCompleteStop = stopCallback;
144 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStart = waitForTaskCompleteSuspendStartCallback;
145 | tsConfig.profilerCallbacks.waitForTaskCompleteSuspendStop = stopCallback;
146 |
147 | g_TS.Initialize( tsConfig );
148 |
149 |
150 | rmt_SetCurrentThreadName("Main");
151 |
152 | double avSpeedUp = 0.0;
153 | for( int run = 0; run< RUNS; ++run )
154 | {
155 | rmt_ScopedCPUSample(Run, 0);
156 |
157 | printf("Run %d\t Open Remotery\\vis\\index.html to view profiler\n", run);
158 | ParallelReductionSumTaskSet m_ParallelReductionSumTaskSet( SUMS );
159 | {
160 | rmt_ScopedCPUSample(Parallel, 0);
161 |
162 | m_ParallelReductionSumTaskSet.Init();
163 |
164 | g_TS.AddTaskSetToPipe(&m_ParallelReductionSumTaskSet);
165 |
166 | g_TS.WaitforTask(&m_ParallelReductionSumTaskSet);
167 | }
168 |
169 |
170 |
171 | uint64_t sum = 0;
172 | {
173 | rmt_ScopedCPUSample(Serial, 0);
174 | for (uint64_t i = 0; i < (uint64_t)m_ParallelReductionSumTaskSet.m_ParallelSumTaskSet.m_SetSize; ++i)
175 | {
176 | sum += i + 1;
177 | }
178 | }
179 | printf("Sun Parallel: %" PRIu64 ", sum serial %" PRIu64, m_ParallelReductionSumTaskSet.m_FinalSum, sum );
180 | if( m_ParallelReductionSumTaskSet.m_FinalSum == sum )
181 | {
182 | printf(" - Sums Correct.\n");
183 | }
184 | else
185 | {
186 | assert(false);
187 | printf(" - Sums ERROR.\n");
188 | }
189 |
190 | }
191 | g_TS.WaitforAllAndShutdown();
192 | rmt_DestroyGlobalInstance(rmt);
193 | return 0;
194 | }
195 |
--------------------------------------------------------------------------------
/images/enkiTSMicroprofileExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dougbinks/enkiTSExamples/b0438f94ff99203fb6eb01c8871ea3f5b1bbecf5/images/enkiTSMicroprofileExample.png
--------------------------------------------------------------------------------
/images/enkiTSRemoteryExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dougbinks/enkiTSExamples/b0438f94ff99203fb6eb01c8871ea3f5b1bbecf5/images/enkiTSRemoteryExample.png
--------------------------------------------------------------------------------