/* cilkview.h -*-C++-*- * ************************************************************************* * * @copyright * Copyright (C) 2010-2013, Intel Corporation * All rights reserved. * * @copyright * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * @copyright * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ #ifndef INCLUDED_CILKVIEW_H #define INCLUDED_CILKVIEW_H #include #ifdef _WIN32 # ifndef _WINBASE_ __CILKRTS_BEGIN_EXTERN_C unsigned long __stdcall GetTickCount(); __CILKRTS_END_EXTERN_C # endif #endif // _WIN32 #if defined __unix__ || defined __APPLE__ || defined __VXWORKS__ # include #endif // defined __unix__ || defined __APPLE__ /// @brief Return the system clock with millisecond resolution /// /// This function returns a long integer representing the number of /// milliseconds since an arbitrary starting point, e.g., since the system was /// started or since the Unix Epoch. The result is meaningless by itself, but /// the difference between two sequential calls to __cilkview_getticks() /// represents the time interval that elapsed between them (in ms). static inline unsigned long long __cilkview_getticks() { #if __INTEL_COMPILER > 1200 // When inlined, prevent code motion around this call __notify_zc_intrinsic((void*) "test_getticks_start", 0); #endif #ifdef _WIN32 // Return milliseconds elapsed since the system started return GetTickCount(); #elif defined(__unix__) || defined(__APPLE__) || defined __VXWORKS__ // Return milliseconds elapsed since the Unix Epoch // (1-Jan-1970 00:00:00.000 UTC) struct timeval t; gettimeofday(&t, 0); return t.tv_sec * 1000ULL + t.tv_usec / 1000; #else # error test_getticks() not implemented for this OS #endif #if __INTEL_COMPILER > 1200 // When inlined, prevent code motion around this call __notify_zc_intrinsic((void*) "test_getticks_end", 0); #endif } typedef struct { unsigned int size; // Size of structure in bytes unsigned int status; // 1 = success, 0 = failure unsigned long long time; // Time in milliseconds unsigned long long work; unsigned long long span; unsigned long long burdened_span; unsigned long long spawns; unsigned long long syncs; unsigned long long strands; unsigned long long atomic_ins; unsigned long long frames; } cilkview_data_t; typedef struct { cilkview_data_t *start; // Values at start of interval cilkview_data_t *end; // Values at end of interval const char *label; // Name for this interval unsigned int flags; // What to do - see flags below } cilkview_report_t; // What __cilkview_report should do. The flags can be ORed together enum { CV_REPORT_WRITE_TO_LOG = 1, // Write parallelism report to the log (xml or text) CV_REPORT_WRITE_TO_RESULTS = 2 // Write parallelism data to results file }; #ifndef CILKVIEW_NO_REPORT static void __cilkview_do_report(cilkview_data_t *start, cilkview_data_t *end, const char *label, unsigned int flags); #endif /* CILKVIEW_NO_REPORT */ /* * Metacall data * * A metacall is a way to pass data to a function implemented by a tool. * Metacalls are always instrumented when the tool is loaded. */ // Tool code for Cilkview #define METACALL_TOOL_CILKVIEW 2 // Metacall codes implemented by Cilkview enum { CV_METACALL_PUTS, CV_METACALL_QUERY, CV_METACALL_START, CV_METACALL_STOP, CV_METACALL_RESET, CV_METACALL_USE_DEFAULT_GRAIN, CV_METACALL_CONNECTED, CV_METACALL_SUSPEND, CV_METACALL_RESUME, CV_METACALL_REPORT }; #if ! defined(CILK_STUB) && defined(__INTEL_COMPILER) # define __cilkview_metacall(code,data) \ __cilkrts_metacall(METACALL_TOOL_CILKVIEW, code, data) #else # define __cilkview_metacall(annotation,expr) (annotation, (void) (expr)) #endif // Write arbitrary string to the log #define __cilkview_puts(arg) \ __cilkview_metacall(CV_METACALL_PUTS, arg) // Retrieve the Cilkview performance counters. The parameter must be a // cilkview_data_t #define __cilkview_query(d) \ do { \ d.size = sizeof(d); \ d.status = 0; \ __cilkview_metacall(CV_METACALL_QUERY, &d); \ if (0 == d.status) \ d.time = __cilkview_getticks(); \ } while (0) // Write report to log or results file. If end is NULL, Cilkview will // use the current values. #define __cilkview_report(start, end, label, flags) \ __cilkview_do_report(start, end, label, flags) // Control the workspan performance counters for the final report #define __cilkview_workspan_start() \ __cilkview_metacall(CV_METACALL_START, 0) #define __cilkview_workspan_stop() \ __cilkview_metacall(CV_METACALL_STOP, 0) #define __cilkview_workspan_reset() \ __cilkview_metacall(CV_METACALL_RESET, 0) #define __cilkview_workspan_suspend() \ __cilkview_metacall(CV_METACALL_SUSPEND, 0) #define __cilkview_workspan_resume() \ __cilkview_metacall(CV_METACALL_RESUME, 0) #define __cilkview_use_default_grain_size() \ __cilkview_metacall(CV_METACALL_USE_DEFAULT, 0) // Sets the int is_connected to 1 if Cilkview is active #define __cilkview_connected(is_connected) \ __cilkview_metacall(CV_METACALL_CONNECTED, &is_connected) #ifndef CILKVIEW_NO_REPORT // Stop Microsoft include files from complaining about getenv and fopen #define _CRT_SECURE_NO_WARNINGS #include #include #ifdef _WIN32 #pragma warning(push) #pragma warning(disable: 1786) // Suppress warnings that getenv, fopen are deprecated #endif static void __cilkview_do_report(cilkview_data_t *start, cilkview_data_t *end, const char *label, unsigned int flags) { int under_cilkview = 0; unsigned long long elapsed_ms; int worker_count = 0; char *nworkers; char *outfile; FILE *f; // Check whether we're running under Cilkview __cilkview_connected(under_cilkview); // If we're running under Cilkview, let it do those things that need // to be done if (under_cilkview) { cilkview_report_t d = {start, end, label, flags}; __cilkview_metacall(CV_METACALL_REPORT, &d); return; } // We're not running under Cilkview. // // If we weren't asked to write to the results file, we're done. if (0 == (flags & CV_REPORT_WRITE_TO_RESULTS)) return; // Calculate the elapse milliseconds if (NULL == end) elapsed_ms = __cilkview_getticks() - start->time; else elapsed_ms = end->time - start->time; // Determine how many workers we're using for this trial run nworkers = getenv("CILK_NWORKERS"); if (NULL != nworkers) worker_count = atoi(nworkers); if (0 == worker_count) worker_count = 16; // Open the output file and write the trial data to it outfile = getenv("CILKVIEW_OUTFILE"); if (NULL == outfile) outfile = (char *)"cilkview.out"; f = fopen(outfile, "a"); if (NULL == f) fprintf(stderr, "__cilkview_do_report: unable to append to file %s\n", outfile); else { fprintf(f, "%s trial %d %f\n", label, worker_count, ((float)elapsed_ms) / 1000.0f); fclose(f); } } #ifdef _WIN32 #pragma warning(pop) #endif #endif // CILKVIEW_NO_REPORT #endif /* ! defined(INCLUDED_CILKVIEW_H) */