├── .gitignore ├── LICENSE ├── Makefile ├── README ├── backend ├── .gitignore ├── BasicBlockTime │ ├── .gitignore │ ├── Makefile │ ├── README │ ├── bbDelta.cpp │ ├── bbDelta.hpp │ ├── main.cpp │ ├── plot.py │ └── traverse.cpp ├── CodeSimilar │ ├── .gitignore │ ├── Makefile │ ├── README │ ├── main.cpp │ └── plot.py ├── Comm2 │ ├── .gitignore │ ├── Makefile │ ├── README │ ├── comm.cpp │ ├── commFileIO.cpp │ ├── commFileIO.hpp │ └── gridPlot.py ├── CommTracker │ ├── CommRecord.cpp │ ├── CommRecord.hpp │ ├── CommTracker.cpp │ ├── CommTracker.hpp │ └── Makefile ├── CritPath │ ├── .gitignore │ ├── Makefile │ ├── README.txt │ ├── genCritPath.py │ ├── main.cpp │ └── plot.py ├── DynamicAnalysis │ ├── .gitignore │ ├── CMakeLists.txt │ ├── DynamicAnalysis.cpp │ ├── DynamicAnalysis.h │ ├── Execution.cpp │ ├── Final.cpp │ ├── Init.cpp │ ├── Params.h │ ├── Print.cpp │ ├── README │ ├── TBV.cpp │ ├── run.py │ └── top-down-size-splay.hpp ├── DynamicCFG │ ├── .gitignore │ ├── BasicBlock.cpp │ ├── BasicBlock.hpp │ ├── Makefile │ ├── dynamicCFG.cpp │ └── output │ │ └── .gitignore ├── EasyProf │ ├── Makefile │ ├── README │ ├── easyProf.cpp │ ├── easyViz.cpp │ └── usage ├── Harmony │ ├── .gitignore │ ├── Makefile │ ├── README │ ├── harmony.py │ └── main.cpp ├── Heltech │ ├── .gitignore │ ├── Makefile │ ├── README │ ├── heltech.cpp │ └── heltech.hpp ├── MemUse │ ├── Makefile │ ├── README │ ├── main.cpp │ ├── memUse.cpp │ ├── memUse.hpp │ └── memuse.py ├── RemSync │ ├── Makefile │ ├── README.txt │ └── remSync.cpp ├── SCacheOrder │ ├── .gitignore │ ├── Makefile │ ├── TraceWrapper.cpp │ ├── TraceWrapper.hpp │ ├── main.cpp │ ├── plot.py │ ├── simpleCache.cpp │ └── simpleCache.hpp ├── SimpleCache │ ├── .gitignore │ ├── Makefile │ ├── main.cpp │ ├── plot.py │ ├── simpleCache.cpp │ └── simpleCache.hpp ├── Statistics │ ├── .gitignore │ ├── Makefile │ └── stats.cpp ├── TaskGraphFrontEnd │ ├── IFrontEnd.hpp │ ├── Makefile │ ├── TaskGraphFrontEnd.cpp │ ├── TaskGraphFrontEnd.hpp │ ├── TaskGraphFrontEnd_test.cpp │ ├── markedBlock.cpp │ ├── markedBlock.hpp │ ├── markedCodeContainer.cpp │ ├── markedCodeContainer.hpp │ ├── markedCodeContainer_test.cpp │ ├── markedInstruction.cpp │ └── markedInstruction.hpp └── TaskGraphVisualizer │ ├── .gitignore │ ├── Makefile │ ├── output │ ├── .gitignore │ └── about.txt │ └── taskViz.cpp ├── common ├── eventLib │ ├── Makefile │ ├── ct_event.cpp │ ├── ct_event.h │ └── ct_event_st.h ├── runtime │ ├── Makefile │ ├── ct_main.c │ ├── ct_mpi.c │ ├── ct_nompi.c │ ├── ct_runtime.c │ ├── ct_runtime.h │ ├── mpi.h │ └── rdtsc.h └── taskLib │ ├── .gitignore │ ├── Action.cpp │ ├── Action.hpp │ ├── Backend.cpp │ ├── Backend.hpp │ ├── Makefile │ ├── Task.cpp │ ├── Task.hpp │ ├── TaskGraph.cpp │ ├── TaskGraph.hpp │ ├── TaskGraphInfo.cpp │ ├── TaskGraphInfo.hpp │ ├── TaskId.hpp │ ├── ct_file.c │ └── ct_file.h ├── ct_logo.png ├── llvm-contech ├── .gitignore ├── BufferCheckAnalysis.cpp ├── BufferCheckAnalysis.h ├── BufferSizeAnalysis.cpp.bak ├── BufferSizeAnalysis.h ├── CMakeLists.txt ├── Contech.cpp ├── Contech.exports ├── Contech.h ├── ContechDef.h ├── LoopIV.cpp ├── LoopIV.h ├── Path.cpp ├── README └── Support.cpp ├── llvm └── lib │ └── Transforms │ ├── Contech │ ├── CMakeLists.txt │ ├── Contech.cpp │ ├── Contech.exports │ ├── Contech.h │ └── Makefile │ └── DynamicAnalysis │ ├── DynamicAnalysis.cpp │ ├── DynamicAnalysis.exports │ ├── DynamicAnalysis.h │ ├── Execution.cpp │ ├── Final.cpp │ ├── Init.cpp │ ├── Makefile │ ├── Params.h │ ├── Print.cpp │ ├── README │ ├── TBV.cpp │ └── top-down-size-splay.hpp ├── middle ├── .gitignore ├── BarrierWrapper.cpp ├── BarrierWrapper.hpp ├── Context.cpp ├── Context.hpp ├── Makefile ├── eventQ.cpp ├── eventQ.hpp ├── middle.cpp ├── middle.hpp ├── output │ ├── .gitignore │ └── about.txt ├── taskWrite.cpp └── taskWrite.hpp ├── pin └── contech_fe.cpp └── scripts ├── .gitignore ├── aggregate_scrape_run.py ├── batch.py ├── build_nas.py ├── build_parsec.py ├── clear_cache.sh ├── contech_marker++.py ├── contech_marker.py ├── contech_wrapper++.py ├── contech_wrapper.py ├── contech_wrapper_minimal++.py ├── contech_wrapper_minimal.py ├── contech_wrapper_par++.py ├── contech_wrapper_par.py ├── mark_parsec.py ├── objparse.py ├── output └── .gitignore ├── overhead-scrape.py ├── overhead.py ├── perf-scrape.py ├── perf.py ├── prepare_for_manifold.py ├── qscrape.py ├── regress-local.py ├── regress-nas.py ├── regress.py ├── run.py ├── run_nas.py ├── run_parsec.py ├── run_rodinia.py ├── scrape_build.py ├── scrape_run.py ├── uniq_ar_x.sh └── util.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.bc 4 | *.pyc 5 | *.csv 6 | *.pdf 7 | *.o????? 8 | *.e????? 9 | nohup.out 10 | llvm/lib/Transforms/lib/ 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Georgia Institute of Technology 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. The name of the organization may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CLEAN_DIRS=\ 2 | common/eventLib \ 3 | common/runtime \ 4 | common/taskLib \ 5 | backend/CommTracker \ 6 | backend/Statistics \ 7 | backend/Comm2 \ 8 | backend/TaskGraphFrontEnd \ 9 | backend/Heltech \ 10 | backend/Harmony \ 11 | middle \ 12 | 13 | GRAPHVIZ_TOOLS = \ 14 | backend/DynamicCFG \ 15 | backend/TaskGraphVisualizer \ 16 | 17 | 18 | MAKE_DIRS = $(CLEAN_DIRS) 19 | 20 | 21 | all: multimake 22 | 23 | multimake: $(CLEAN_DIRS) 24 | 25 | .PHONY: multimake $(CLEAN_DIRS) 26 | 27 | $(CLEAN_DIRS): 28 | $(MAKE) -C $@ 29 | 30 | viz_backends: 31 | for d in $(GRAPHVIZ_TOOLS); \ 32 | do \ 33 | echo ""; echo -e "\033[94m$$d \033[0m"; \ 34 | make -C $$d; \ 35 | if [[ $$? -ne 0 ]]; then \ 36 | echo -e "\033[91m Compilation failed! \033[0m"; \ 37 | exit 1; \ 38 | fi; \ 39 | done; 40 | 41 | clean: 42 | for d in $(CLEAN_DIRS); \ 43 | do \ 44 | make clean -C $$d; \ 45 | done; \ 46 | 47 | 48 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Contech is an open source framework for collecting and analyzing task graphs. 2 | 3 | Limited documentation is available in the github wiki - https://github.com/bprail/contech/wiki 4 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.out 3 | *.json 4 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/.gitignore: -------------------------------------------------------------------------------- 1 | output 2 | traverse 3 | bbTime 4 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | PROJECT = bbTime 3 | OBJECTS = main.o bbDelta.o 4 | CPPFLAGS = -O3 -g --std=c++11 -I../../common/taskLib/ 5 | LIBS = -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | 7 | all: $(PROJECT) traverse 8 | 9 | $(PROJECT): $(OBJECTS) 10 | $(CXX) $(OBJECTS) $(LIBS) -o $(PROJECT) 11 | 12 | traverse: traverse.o 13 | $(CXX) traverse.o $(LIBS) -o traverse 14 | 15 | clean: 16 | rm -f $(PROJECT) $(OBJECTS) 17 | 18 | 19 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/README: -------------------------------------------------------------------------------- 1 | BasicBlockTime backend 2 | 3 | This backend requires an alternative compilation of the LLVM PASS to add 4 | time stamps to every basic block. While seemingly desirable, this 5 | significantly increases the runtime overhead and most blocks show low 6 | times. Most blocks have a long tail from context switches and other 7 | exceptional events. 8 | 9 | See TSC_IN_BB in llvm-contech/Contech.cpp 10 | 11 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/bbDelta.cpp: -------------------------------------------------------------------------------- 1 | #include "bbDelta.hpp" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | using namespace contech; 7 | 8 | BBDeltaBackend::BBDeltaBackend() 9 | { 10 | resetBackend(); 11 | } 12 | 13 | void BBDeltaBackend::initBackend(TaskGraphInfo* tgi) 14 | { 15 | this->tgi = tgi; 16 | } 17 | 18 | void BBDeltaBackend::updateBackend(Task* currentTask) 19 | { 20 | instTime += currentTask->getEndTime() - currentTask->getStartTime(); 21 | //if (currentTask->getContextId() == 0) return; 22 | switch(currentTask->getType()) 23 | { 24 | case task_type_basic_blocks: 25 | { 26 | uint32_t bbid = 0, lastBBID = 0; 27 | uint64_t prevTime = 0, currTime = 0, delta = 0; 28 | bool lastBlockCall = false, hasUninstCall = false , hasUninstTime = false; 29 | string lastFuncName; 30 | auto bba = currentTask->getBasicBlockActions(); 31 | for (auto f = bba.begin(), e = bba.end(); f != e; ++f) 32 | { 33 | currTime = 0; 34 | BasicBlockAction bb = *f; 35 | 36 | bbid = (uint)bb.basic_block_id; 37 | auto bbCall = bbInstCall.find(bbid); 38 | 39 | if (lastBlockCall || bbCall == bbInstCall.end()) 40 | { 41 | auto bbi = tgi->getBasicBlockInfo(bbid); 42 | if (lastBlockCall) 43 | { 44 | // There was a function call in the last basic block 45 | // If the next block is in the same function, then 46 | // the function was not instrumented, or recursion? 47 | if (lastFuncName == bbi.functionName) 48 | { 49 | bbInstCall[lastBBID] = false; 50 | } 51 | else 52 | { 53 | bbInstCall[lastBBID] = true; 54 | } 55 | lastBlockCall = false; 56 | } 57 | if (bbCall == bbInstCall.end()) 58 | { 59 | if((bbi.flags & BBI_FLAG_CONTAIN_CALL) == BBI_FLAG_CONTAIN_CALL) 60 | { 61 | lastBlockCall = true; 62 | lastFuncName = bbi.functionName; 63 | } 64 | else 65 | { 66 | // This block is followed by an instrumented block 67 | bbInstCall[bbid] = true; 68 | } 69 | } 70 | } 71 | 72 | for (MemoryAction mem : f.getMemoryActions()) 73 | { 74 | if (currTime == 0) {currTime = mem.addr;} 75 | if (Action(mem).isMemOp() == false) 76 | { 77 | bbInstCall[bbid] = true; 78 | hasUninstCall = false; 79 | } 80 | } 81 | if (prevTime == 0) 82 | { 83 | // Math from start Time? 84 | prevTime = currTime; 85 | lastBBID = bbid; 86 | continue; 87 | } 88 | //if (currTime < 89 | assert(currTime >= prevTime); 90 | delta = currTime - prevTime; 91 | 92 | if (bbInstCall.find(lastBBID) != bbInstCall.end() && bbInstCall[lastBBID] == false) 93 | { 94 | uninstTime += delta; 95 | bbHistogram[lastBBID][0] += delta; 96 | } 97 | 98 | if (bbInstCall[bbid] == false && hasUninstCall == true) 99 | { 100 | hasUninstTime = true; 101 | } 102 | 103 | 104 | //if (bbid == 190) 105 | // printf("%u\n", (uint32_t)delta); 106 | prevTime = currTime; 107 | lastBBID = bbid; 108 | } 109 | } 110 | break; 111 | default: 112 | { 113 | 114 | } 115 | break; 116 | } 117 | } 118 | 119 | void BBDeltaBackend::resetBackend() 120 | { 121 | bbHistogram.clear(); 122 | instTime = 0; 123 | uninstTime = 0; 124 | } 125 | 126 | void BBDeltaBackend::completeBackend(FILE* f, contech::TaskGraphInfo* tgi) 127 | { 128 | fprintf(f, "%llu, %llu, %lf\n", instTime, uninstTime, 1.0 - ((double)uninstTime)/ 129 | ((double)(instTime))); 130 | for (auto it = bbHistogram.begin(), et = bbHistogram.end(); it != et; ++it) 131 | { 132 | fprintf(f, "%u, ",it->first); 133 | auto bbi = tgi->getBasicBlockInfo(it->first); 134 | auto bbic = bbInstCall.find(it->first); 135 | 136 | fprintf(f, "%u, %u, %u, %u, %u, ", bbi.flags, (!bbic->second), bbi.numOfMemOps, bbi.numOfOps, bbi.critPathLen); 137 | 138 | for (auto itv = it->second.begin(), etv = it->second.end(); itv != etv; ++itv) 139 | { 140 | fprintf(f, "%u, %u, ", itv->first, itv->second); 141 | } 142 | fprintf(f, "%s:%d\n", bbi.fileName.c_str(), bbi.lineNumber); 143 | } 144 | fflush(f); 145 | } 146 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/bbDelta.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BBDELTA_HPP 2 | #define BBDELTA_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class BBDeltaBackend : public contech::Backend 11 | { 12 | std::map > bbHistogram; 13 | std::map bbInstCall; 14 | contech::TaskGraphInfo* tgi; 15 | uint64_t instTime, uninstTime; 16 | 17 | public: 18 | virtual void initBackend(contech::TaskGraphInfo*); 19 | virtual void resetBackend(); 20 | virtual void updateBackend(contech::Task*); 21 | virtual void completeBackend(FILE*, contech::TaskGraphInfo*); 22 | 23 | BBDeltaBackend(); 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /backend/BasicBlockTime/main.cpp: -------------------------------------------------------------------------------- 1 | #include "bbDelta.hpp" 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | if (argc < 2) 7 | { 8 | fprintf(stderr, "%s \n", argv[0]); 9 | return 1; 10 | } 11 | 12 | BBDeltaBackend* bsc = new BBDeltaBackend(); 13 | contech::SimpleBackendWrapper* sbw = new contech::SimpleBackendWrapper(argv[1], bsc); 14 | 15 | sbw->initBackend(); 16 | sbw->runBackend(); 17 | sbw->completeRun(stdout); 18 | delete sbw; 19 | delete bsc; 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /backend/CodeSimilar/.gitignore: -------------------------------------------------------------------------------- 1 | output/* 2 | codeS 3 | temp* 4 | -------------------------------------------------------------------------------- /backend/CodeSimilar/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | PROJECT = codeS 3 | OBJECTS = main.o 4 | #TEST_PROJECT = lockAnalysis_test 5 | #TEST_OBJECTS = ct_event_mock.o LockAnalysis.o lockAnalysis_test.o 6 | CPPFLAGS = -O3 -g --std=c++11 7 | LIBS = -lct_event -L../../common/eventLib/ -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 8 | 9 | all: $(PROJECT) 10 | 11 | $(PROJECT): $(OBJECTS) 12 | $(CXX) $(OBJECTS) $(LIBS) -o $(PROJECT) 13 | 14 | #ct_event_mock.o: 15 | # $(CXX) -O3 -g -c -o ct_event_mock.o ct_event_mock.c 16 | 17 | #test: $(TEST_OBJECTS) 18 | # $(CXX) $(TEST_OBJECTS) -o $(TEST_PROJECT) 19 | # ./lockAnalysis_test 20 | 21 | clean: 22 | rm -f $(PROJECT) $(OBJECTS) 23 | # rm -f $(TEST_PROJECT) $(TEST_OBJECTS) 24 | 25 | 26 | -------------------------------------------------------------------------------- /backend/CodeSimilar/README: -------------------------------------------------------------------------------- 1 | CodeSimilar - This tool measures the similarity of code executed by different 2 | contexts in the program. 3 | 4 | -------------------------------------------------------------------------------- /backend/CodeSimilar/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../../common/taskLib/ct_file.h" 2 | #include "../../common/taskLib/TaskGraph.hpp" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | using namespace contech; 13 | 14 | #define MAX_THREADS 1024 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | //input check 19 | if(argc != 2){ 20 | cout << "Usage: " << argv[0] << " taskGraphInputFile" << endl; 21 | exit(1); 22 | } 23 | 24 | FILE* taskGraphIn = fopen(argv[1], "rb"); 25 | if (taskGraphIn == NULL) { 26 | cerr << "ERROR: Couldn't open input file" << endl; 27 | exit(1); 28 | } 29 | 30 | 31 | TaskGraph* tg = TaskGraph::initFromFile(taskGraphIn); 32 | if (tg == NULL) {} 33 | 34 | // BBID -> set of Contexts 35 | map > bbExecMap; 36 | bool firstCreate = false; 37 | 38 | while(Task* currentTask = tg->readContechTask()) 39 | { 40 | TaskId ctui = currentTask->getTaskId(); 41 | ContextId ctci = currentTask->getContextId(); 42 | 43 | if (firstCreate == true) 44 | { 45 | ; 46 | } 47 | else 48 | { 49 | if (currentTask->getType() != task_type_create) 50 | { 51 | delete currentTask; 52 | continue; 53 | } 54 | firstCreate = true; 55 | } 56 | 57 | auto bba = currentTask->getBasicBlockActions(); 58 | for (auto bbit = bba.begin(), bbet = bba.end(); bbit != bbet; ++bbit) 59 | { 60 | unsigned int bbid = ((BasicBlockAction)*bbit).basic_block_id; 61 | 62 | bbExecMap[bbid].insert(ctci); 63 | } 64 | 65 | delete currentTask; 66 | } 67 | delete tg; 68 | 69 | ContextId czero = ContextId(0); 70 | for (auto bbvit = bbExecMap.begin(), bbvet = bbExecMap.end(); bbvit != bbvet; ++bbvit) 71 | { 72 | printf("%u, %u, ", bbvit->first, bbvit->second.size()); 73 | bbvit->second.erase(czero); 74 | printf("%u\n", bbvit->second.size()); 75 | } 76 | 77 | fclose(taskGraphIn); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /backend/CodeSimilar/plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.colors as colors 15 | import matplotlib as matplotlib 16 | import json 17 | import math 18 | import csv 19 | 20 | #This script parses the Harmony backend output to plot (thread count, exec count) tuples 21 | def main(arg): 22 | if (len(arg)) == 1: 23 | print "Usage: {0} input\n".format(arg[0]) 24 | exit() 25 | 26 | p = 1 27 | 28 | fig = plt.figure(figsize=(7, 7)) 29 | for harmony_in in arg[1:]: 30 | execTuple = [] 31 | threadTuple = [] 32 | zeroTuple = [] 33 | max_threads = 0 34 | avg_val = 0 35 | with open(harmony_in, "r") as csvfile: 36 | #sorry to use blah, but I blanked on a name for this latest temp 37 | blah = csv.reader(csvfile) 38 | i = 0 39 | for row in blah: 40 | 41 | r = map(int, row) 42 | if (len(r) == 2): 43 | continue 44 | sval = r[1] # includes 0:* 45 | zval = r[2] # removes 0:* 46 | 47 | execTuple.append(i) 48 | val = zval 49 | 50 | if (sval > zval): 51 | zeroTuple.append(sval) 52 | val = sval 53 | else: 54 | threadTuple.append(zval) 55 | val = zval 56 | if val > max_threads: 57 | max_threads = val 58 | avg_val += val 59 | i += 1 60 | if i == 0: 61 | continue 62 | avg_val /= i 63 | 64 | if (p <= 28): 65 | if (len(arg) == 2): 66 | ax = fig.add_subplot(1,1, p) 67 | else: 68 | ax = fig.add_subplot(7,4, p) 69 | #plt.xlim(0, 17) 70 | #plt.plot(threadTuple, execTuple, 'k.', linestyle='None') 71 | 72 | tHist = [0.0] * (max_threads + 1) 73 | zHist = [0.0] * (max_threads + 1) 74 | print len(tHist) 75 | for t in threadTuple: 76 | tHist[t] += 1.0 77 | 78 | for z in zeroTuple: 79 | zHist[z] += 1.0 80 | 81 | nsum = sum(tHist) + sum(zHist) 82 | tFin = [] 83 | for t in tHist: 84 | tFin.append(int(100.0 * (t / nsum))) 85 | 86 | zFin = [] 87 | for z in zHist: 88 | zFin.append(int(100.0 * (z / nsum))) 89 | 90 | xval = range(0, max_threads+1) 91 | leftv = [] 92 | for x in xval: 93 | leftv.append(x - 0.4) 94 | plt.bar(leftv, tFin, width=0.85,color='b') 95 | plt.bar(leftv, zFin, width=0.85,color='g', bottom=tFin) 96 | #plt.hist([tFin,zFin], bins=max_threads, align='left',stacked=True) 97 | plt.ylim(0,100) 98 | plt.vlines(avg_val, 0, 100, colors='r') 99 | 100 | if (len(arg) == 2): 101 | plt.xticks(fontsize=12) 102 | plt.yticks(fontsize=12) 103 | else: 104 | 105 | if (p % 4 == 1): 106 | p = p 107 | elif (p % 4 == 0): 108 | ax.yaxis.tick_right() 109 | ax.yaxis.set_ticks_position('both') 110 | else: 111 | ax.set_yticklabels([]) 112 | plt.xticks(fontsize=5) 113 | plt.yticks(fontsize=5) 114 | 115 | plt.tick_params(axis='y', which='minor', left='off', right='off') 116 | harmony_l = harmony_in.split('/') 117 | harmony_in = harmony_l[-1] 118 | harmony_l = harmony_in.split('.') 119 | harmony_in = harmony_l[-2] 120 | t = plt.title(harmony_in, fontsize=5, verticalalignment='bottom') 121 | (x,y) = t.get_position() 122 | t.set_position((x, (y- 0.07))) 123 | p += 1 124 | plt.subplots_adjust(left=0.05, top = 0.98, bottom = 0.05, wspace = 0.1, hspace = 0.27) 125 | fig.text(0.5, 0.02, 'Unique Contexts', ha='center', va='center', fontsize=7) 126 | fig.text(0.01, 0.5, 'Fraction of Contexts Executing a Basic Block', ha='center', va='center', rotation='vertical', fontsize=7) 127 | 128 | plt.savefig( "temp.png") 129 | plt.savefig( "temp.pdf") 130 | 131 | 132 | if __name__ == "__main__": 133 | main(sys.argv) 134 | -------------------------------------------------------------------------------- /backend/Comm2/.gitignore: -------------------------------------------------------------------------------- 1 | comm 2 | -------------------------------------------------------------------------------- /backend/Comm2/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CXX=g++ 3 | CFLAGS= -g -O3 4 | CXXFLAGS= -g -std=c++11 -O3 5 | OBJECTS= comm.o commFileIO.o 6 | INCLUDES= 7 | LIBS= -L../../common/taskLib/ -lTask -L../CommTracker -lCommTracker -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 8 | EXTERNALS= 9 | 10 | all: taskLib comm 11 | 12 | taskLib: 13 | make -C ../../common/taskLib 14 | 15 | %.o : %.cpp 16 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 17 | comm: $(OBJECTS) 18 | $(CXX) $^ $(CXXFLAGS) $(LIBS) $(EXTERNALS) -o $@ 19 | 20 | clean: 21 | rm -f *.o 22 | rm -f comm 23 | -------------------------------------------------------------------------------- /backend/Comm2/README: -------------------------------------------------------------------------------- 1 | Comm2 - communication analysis tool that uses the CommTracker library to 2 | identify communication (e.g., reads after writes) between different basic 3 | blocks and different tasks in the task graph. 4 | 5 | -------------------------------------------------------------------------------- /backend/Comm2/commFileIO.hpp: -------------------------------------------------------------------------------- 1 | #include "../../common/taskLib/Task.hpp" 2 | #include "../CommTracker/CommTracker.hpp" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | using namespace std; 13 | class commFileIO; 14 | class commFileIORecord { 15 | public: 16 | ct_sharers_t destMask; 17 | unsigned int count; 18 | 19 | //constructor 20 | commFileIORecord(ct_sharers_t destMask,unsigned int count); 21 | void print(); 22 | 23 | }; 24 | 25 | 26 | class commFileIO { 27 | private: 28 | static set getSharersFromBitVector(uint64_t sharers); 29 | public: 30 | commFileIO(); 31 | 32 | //mapping of a basic block signature (0|1,2,3,4,) to a commFileIORecord 33 | //which is identified by a destMask and count of communication 34 | unordered_map> commFileIORecords; 35 | unordered_map> createMap(); 36 | 37 | //functions to get data into and out of files 38 | void serialize(string filename); 39 | void deserialize(string filename); 40 | 41 | void print(); 42 | ct_sharers_t predictStableMax(contech::ContextId srcThread, string basicBlockSignature); 43 | ct_sharers_t predictMax(contech::ContextId srcThread, string basicBlockSignature); 44 | ct_sharers_t predictAboveAverage(contech::ContextId srcThread, string basicBlockSignature); 45 | 46 | 47 | // TODO Migratory data predictions 48 | 49 | }; 50 | -------------------------------------------------------------------------------- /backend/Comm2/gridPlot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import argparse 8 | import subprocess 9 | import shutil 10 | import time 11 | import datetime 12 | import glob 13 | import matplotlib 14 | #matplotlib.use('Agg') 15 | import numpy as np 16 | import matplotlib.pyplot as plt 17 | import json 18 | import math 19 | 20 | 21 | def main(): 22 | 23 | # Parse commandline arguments 24 | parser = argparse.ArgumentParser(description="Runs benchmark that has been compiled with contech, generating a task graph and optionally running backend tools.") 25 | parser.add_argument("inFile", help="Input file, a json file of commRecords") 26 | parser.add_argument("outFile", help="Output file, a png of inter-thread communication.") 27 | args = parser.parse_args() 28 | 29 | x, y = [], [] 30 | nThreads = 0 31 | print "Loading {}...".format(args.inFile) 32 | with open(args.inFile) as file: 33 | data = json.load(file) 34 | records = data["records"] 35 | print "Loaded {} records".format(len(records)) 36 | 37 | for r in records: 38 | src = int(r["src"].split(":")[0]) 39 | dst = int(r["dst"].split(":")[0]) 40 | nThreads = max([nThreads, src, dst]) 41 | x.append(dst) 42 | y.append(src) 43 | 44 | nThreads = nThreads + 1 # nThreads is the max, ranges need to include it 45 | print "Plotting for {} threads, {} communication records...".format(nThreads, len(x)) 46 | 47 | # plt.title(os.path.basename(args.inFile).replace(".json","")) 48 | plt.xlabel("consumer CPU") 49 | plt.ylabel("producer CPU") 50 | tickPositions = [a + .5 for a in range(nThreads)] 51 | plt.xticks(tickPositions, range(nThreads)) 52 | plt.yticks(tickPositions, range(nThreads)) 53 | plt.hist2d(x, y, bins=nThreads, cmap=matplotlib.cm.Greys) 54 | plt.colorbar() 55 | plt.savefig(args.outFile) 56 | 57 | if __name__ == "__main__": 58 | main() 59 | -------------------------------------------------------------------------------- /backend/CommTracker/CommRecord.cpp: -------------------------------------------------------------------------------- 1 | #include "CommRecord.hpp" 2 | 3 | using namespace contech; 4 | 5 | CommRecord::CommRecord(TaskId sender, uint64_t address, TaskId receiver, uint srcBlock, uint srcPos, uint dstBlock, uint dstPos) 6 | { 7 | this->sender = sender; 8 | this->address = address; 9 | this->receiver = receiver; 10 | 11 | this->srcBlock = srcBlock; 12 | this->srcMemOpPos = srcPos; 13 | this->dstBlock = dstBlock; 14 | this->dstMemOpPos = dstPos; 15 | } 16 | 17 | std::ostream& operator<<(std::ostream& out, const CommRecord& rhs){ 18 | std::string q = "\""; 19 | std::string c = ","; 20 | std::string o = ":"; 21 | 22 | out 23 | 24 | << "{" 25 | 26 | << q << "src" << q << o 27 | << q 28 | << rhs.sender 29 | << q 30 | 31 | << c 32 | 33 | << q << "addr" << q << o 34 | << q 35 | << "0x" << std::hex << rhs.address << std::dec 36 | << q 37 | 38 | << c 39 | 40 | << q << "dst" << q << o 41 | << q 42 | << rhs.receiver 43 | << q 44 | 45 | << c 46 | 47 | << q << "srcB" << q << o 48 | << q 49 | << rhs.srcBlock 50 | << q 51 | 52 | << c 53 | 54 | << q << "dstB" << q << o 55 | << q 56 | << rhs.dstBlock 57 | << q 58 | 59 | << "}"; 60 | 61 | return out; 62 | } 63 | -------------------------------------------------------------------------------- /backend/CommTracker/CommRecord.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COMM_RECORD_H 2 | #define COMM_RECORD_H 3 | 4 | #include "../../common/taskLib/Task.hpp" 5 | 6 | class CommRecord 7 | { 8 | public: 9 | contech::TaskId sender; 10 | uint64_t address; 11 | contech::TaskId receiver; 12 | uint srcBlock; 13 | uint srcMemOpPos; 14 | uint dstBlock; 15 | uint dstMemOpPos; 16 | CommRecord(contech::TaskId sender, uint64_t address, contech::TaskId receiver, uint srcBlock, uint srcPos, uint dstBlock, uint dstPos); 17 | friend std::ostream& operator<<(std::ostream&, const CommRecord&); 18 | }; 19 | 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /backend/CommTracker/CommTracker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COMM_TRACKER_H 2 | #define COMM_TRACKER_H 3 | 4 | 5 | #include "CommRecord.hpp" 6 | #include "../../common/taskLib/TaskGraph.hpp" 7 | #include 8 | #include 9 | #include 10 | 11 | // Type for encoding a set of threads as a bit vector 12 | typedef unsigned long long ct_sharers_t; 13 | 14 | // Per byte address 15 | struct addrEntry 16 | { 17 | // Last writer task 18 | contech::TaskId ownerTask; 19 | // Last reader task 20 | contech::TaskId lastReaderTask; 21 | // Last writer block 22 | uint ownerBlock; 23 | // Last reader block 24 | uint lastReaderBlock; 25 | // Bit vector of sharer threads 26 | ct_sharers_t sharers = 0; 27 | // Position of last writer instruction within the block 28 | short ownerPos; 29 | // Position of last read instruction within the block 30 | short lastReaderPos; 31 | }; 32 | 33 | struct memOpStats 34 | { 35 | // Number of times this memOp did not encounter a coherence miss 36 | uint numHits = 0; 37 | // Number of times this memOp behaved in a migratory way 38 | uint numMigratory = 0; 39 | }; 40 | 41 | // Per basic block 42 | struct bbStats 43 | { 44 | // Number of times this block ran 45 | uint runCount = 0; 46 | // Stats for memOps inside this block 47 | // TODO More efficient way to represent these. Most blocks are very small, but some have dozens of memOps 48 | map memOps; 49 | memOpStats& operator[](uint i) { return memOps[i]; } 50 | }; 51 | 52 | 53 | class CommTracker 54 | { 55 | public: 56 | 57 | void addFree(uint64_t base, contech::TaskId task, uint bbId); 58 | void addAllocate(uint64_t base, unsigned long size, contech::TaskId task, uint bbId); 59 | void addRead (uint64_t addr, unsigned char size, contech::TaskId task, uint bbId, short pos); 60 | void addWrite(uint64_t addr, unsigned char size, contech::TaskId task, uint bbId, short pos); 61 | void countBlock(uint bbId); 62 | vector& getRecords(); 63 | map& getBbStats(); 64 | 65 | static char* getSharersString(ct_sharers_t m); 66 | static ct_sharers_t getSharersMask(contech::TaskId id); 67 | 68 | static CommTracker* fromGraph(contech::TaskGraph*); 69 | static CommTracker* fromFile(FILE* taskGraphIn); 70 | friend std::ostream& operator<<(std::ostream &out, const CommTracker &rhs); 71 | 72 | private: 73 | static CommTracker* runOnGraph(contech::TaskGraph*); 74 | 75 | // Maintains an entry for each address 76 | map addrTable; 77 | 78 | // Remembers size of allocations 79 | map allocation; 80 | 81 | // The complete set of communications that happened in this benchmark 82 | vector records; 83 | 84 | // Maintains communication stats per basic block 85 | map blockTable; 86 | 87 | }; 88 | 89 | 90 | 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /backend/CommTracker/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = libCommTracker.a 2 | CXX=g++ 3 | CXXFLAGS= -g -std=c++11 -O3 4 | OBJECTS= CommTracker.o CommRecord.o 5 | INCLUDES= 6 | LIBS= -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 7 | EXTERNALS= 8 | 9 | all: taskLib $(PROJECT) 10 | 11 | taskLib: 12 | $(MAKE) -C ../../common/taskLib 13 | 14 | %.o : %.cpp 15 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 16 | $(PROJECT): $(OBJECTS) 17 | ar rc $(PROJECT) $(OBJECTS) 18 | 19 | clean: 20 | rm -f *.o 21 | rm -f $(PROJECT) 22 | -------------------------------------------------------------------------------- /backend/CritPath/.gitignore: -------------------------------------------------------------------------------- 1 | output* 2 | tsks* 3 | critPath 4 | -------------------------------------------------------------------------------- /backend/CritPath/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -std=c++11 -O3 3 | OBJECTS= main.o 4 | INCLUDES= 5 | LIBS= -L../../common/taskLib -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | 7 | all: taskLib critPath 8 | 9 | taskLib: 10 | make -C ../../common/taskLib 11 | 12 | %.o : %.cpp 13 | $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< 14 | critPath: $(OBJECTS) 15 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) 16 | 17 | clean: 18 | rm -f *.o 19 | rm -f critPath 20 | -------------------------------------------------------------------------------- /backend/CritPath/README.txt: -------------------------------------------------------------------------------- 1 | CritPath - This backend anaylzes the result files from the Dynamic Analysis backend. 2 | This analysis will then show the critical path through the task graph and the times 3 | required for overall execution. 4 | 5 | See https://github.com/bprail/contech/wiki/Dynamic-Analysis -------------------------------------------------------------------------------- /backend/CritPath/genCritPath.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import argparse 6 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 7 | import util 8 | import subprocess 9 | import shutil 10 | import re 11 | from array import array 12 | 13 | # given a directory (or directories) from dynamic analysis, generate the crit path file 14 | # Format: (all numbers are in binary, speedups are 4byte floats, 15 | # configs, bottlenecks are 2 byte ints, others are 4 byte ints) 16 | # - 17 | # :.._ 18 | def main(arg): 19 | if (len(arg)) == 1: 20 | print "Usage: {0} input\n".format(arg[0]) 21 | exit() 22 | 23 | 24 | f = open( arg[1] + "/critPath.bin", "wb") 25 | 26 | taskCount = 0 27 | confCount = len(arg) - 1 28 | array('h', [confCount]).tofile(f) 29 | array('c', '-').tofile(f) 30 | taskCountPos = f.tell() 31 | array('i', [taskCount]).tofile(f) 32 | 33 | # loop through each context file and add it to the master output 34 | # Will need to simultaneously read from every file in the input directories 35 | for ctFile in os.listdir(arg[1]): 36 | # Skip any files with suffixes 37 | if (len(ctFile.split(".")) > 1): 38 | continue 39 | 40 | ctFileIn = [] 41 | for i in range(confCount): 42 | ctFileIn.append(open(arg[i + 1] + "/" + ctFile, "r")) 43 | 44 | # for each line, first is the context:sequence ID pair 45 | # then header 46 | # then 12 lines of bottlenecks 47 | # skip 3 48 | # then performance 49 | state = 0 50 | context = 0 51 | sequence = 0 52 | for l in ctFileIn[0]: 53 | 54 | confLine = [] 55 | for i in range(1, confCount): 56 | confLine.append(ctFileIn[i].readline()) 57 | 58 | if (state == 0): 59 | m = re.match("\d+:\d+", l) 60 | if (m): 61 | context, sequence = l.split(":") 62 | 63 | state = 1 64 | 65 | continue 66 | if (state == 1): 67 | m = re.match("INT_ADDER", l) 68 | if (m): 69 | state = 2 70 | line = 0 71 | minline = 0 72 | minvalue = -1.0 73 | mintype = 0 74 | else: 75 | continue 76 | if (state == 2): 77 | bvals = l.split() #no arg splits on whitespace 78 | issue = float(bvals[1]) 79 | latency = float(bvals[2]) 80 | if (minvalue == -1.0): 81 | minvalue = issue 82 | minline = line 83 | mintype = 0 84 | if (issue < minvalue and issue > 0.0): 85 | minvalue = issue 86 | minline = line 87 | mintype = 0 88 | if (latency < minvalue and latency > 0.0): 89 | minvalue = latency 90 | minline = line 91 | mintype = 1 92 | line += 1 93 | if (line == 13): 94 | #Rarely, a basic block task is empty and should be skipped. 95 | if (minvalue == -1.0): 96 | state = 0 97 | else: 98 | state = 3 99 | continue 100 | if (state == 3): 101 | m = re.match("PERFORMANCE\s+[0-9.]+", l) 102 | if (m): 103 | state = 0 104 | 105 | array('i', [int(context)]).tofile(f) 106 | array('c', ':').tofile(f) 107 | array('i', [int(sequence)]).tofile(f) 108 | taskCount += 1 109 | 110 | # perf will be used to compare between configs to compute speedup 111 | # versus the first config (i.e. baseline) 112 | perf = float(l.split()[1]) 113 | array('f', [1.0]).tofile(f) 114 | for i in range(1, confCount): 115 | perfConf = float(confLine[i - 1].split()[1]) 116 | array('f', [perfConf / perf]).tofile(f) 117 | array('h', [minline]).tofile(f) 118 | array('c', '_').tofile(f) 119 | array('h', [mintype]).tofile(f) 120 | 121 | for i in range(confCount): 122 | ctFileIn[i].close() 123 | 124 | f.seek(taskCountPos, 0) 125 | array('i', [taskCount]).tofile(f) 126 | f.close() 127 | 128 | if __name__ == "__main__": 129 | main(sys.argv) -------------------------------------------------------------------------------- /backend/DynamicAnalysis/.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | Makefile 4 | cmake_install.cmake 5 | lib 6 | output 7 | -------------------------------------------------------------------------------- /backend/DynamicAnalysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12.2) 2 | 3 | find_package(LLVM REQUIRED CONFIG) 4 | 5 | list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") 6 | include(AddLLVM) 7 | 8 | add_definitions(${LLVM_DEFINITIONS}) 9 | include_directories(${LLVM_INCLUDE_DIRS}) 10 | 11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g") 12 | #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L../../common/taskLib/ -ltaskLib -Wl,-rpath=../../common/taskLib/") 13 | 14 | # AddLLVM needs these 15 | set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) 16 | set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) 17 | 18 | include(HandleLLVMOptions) # important: matches compiler flags to LLVM/Clang build 19 | include(AddLLVM) 20 | 21 | link_directories("../../common/taskLib/") 22 | find_library(TL NAMES libTask.a PATHS "../../common/taskLib/") 23 | 24 | #add_library(LLVMContech MODULE Contech.cpp) 25 | 26 | add_llvm_loadable_module( LLVMDynAnalysis 27 | DynamicAnalysis.cpp 28 | Execution.cpp 29 | Final.cpp 30 | Init.cpp 31 | Print.cpp 32 | TBV.cpp 33 | ) 34 | 35 | 36 | #add_library(taskLib SHARED IMPORTED) 37 | #set(CMAKE_INSTALL_RPATH "../../common/taskLib/") 38 | target_link_libraries(LLVMDynAnalysis Task) -------------------------------------------------------------------------------- /backend/DynamicAnalysis/Params.h: -------------------------------------------------------------------------------- 1 | 2 | #include "llvm/Support/CommandLine.h" 3 | 4 | 5 | //VCA 6 | #include "DynamicAnalysis.h" 7 | using namespace llvm; 8 | 9 | static cl::opt PrintVolatile("interpreter-print-volatile", cl::Hidden, 10 | cl::desc("make the interpreter print every volatile load and store")); 11 | 12 | 13 | //===----------------------------------------------------------------------===// 14 | // VCA: Command line options for application analysis 15 | // 16 | // Command line documentation:http://llvm.org/docs/CommandLine.html 17 | //===----------------------------------------------------------------------===// 18 | static cl::opt PerTaskCommFactor("per-task-comm-factor", cl::desc("Use per task comm factors. Default FALSE"), cl::init(false)); 19 | 20 | static cl::opt CommFactorRead("comm-factor-read", cl::desc("Communication probability factor to scale cache read latency, default 0"), cl::init(0)); 21 | 22 | static cl::opt CommFactorWrite("comm-factor-write", cl::desc("Communication probability factor to scale cache write latency, default 0"), cl::init(0)); 23 | 24 | static cl::opt ContextNumber("context-number", cl::desc("Context # to be analyzed, default 0"), cl::init(0)); 25 | 26 | static cl::opt MemoryWordSize("memory-word-size", cl::desc("Specify the size in bytes of a data item. Default value is 8 (double precision)"),cl::init(8)); 27 | 28 | static cl::opt CacheLineSize("cache-line-size", cl::desc("Specify the cache line size (B). Default value is 64 B"),cl::init(64)); 29 | 30 | static cl::opt L1CacheSize("l1-cache-size", cl::desc("Specify the size of the L1 cache (in bytes). Default value is 32 KB"),cl::init(32768)); 31 | 32 | static cl::opt L2CacheSize("l2-cache-size", cl::desc("Specify the size of the L2 cache (in bytes). Default value is 256 KB"),cl::init(262144)); 33 | 34 | static cl::opt LLCCacheSize("llc-cache-size", cl::desc("Specify the size of the L3 cache (in bytes). Default value is 20 MB"),cl::init(20971520)); 35 | 36 | 37 | static cl::opt Microarchitecture("uarch", cl::desc("Name of the microarchitecture"), 38 | cl::init("SB")); 39 | 40 | static cl::list ExecutionUnitsLatency("execution-units-latency", cl::CommaSeparated, cl::desc("Specify the execution latency of the nodes(cycles). Default value is 1 cycle")); 41 | 42 | 43 | static cl::list ExecutionUnitsThroughput("execution-units-throughput", cl::CommaSeparated, cl::desc("Specify the execution bandwidth of the nodes(ops executed/cycles). Default value is -1 cycle")); 44 | 45 | static cl::list ExecutionUnitsParallelIssue("execution-units-parallel-issue", cl::CommaSeparated, cl::desc("Specify the number of nodes that can be executed in parallel based on ports execution. Default value is -1 cycle")); 46 | 47 | static cl::list MemAccessGranularity("mem-access-granularity", cl::CommaSeparated, cl::desc("Specify the memory access granularity for the different levels of the memory hierarchy (bytes). Default value is memory word size")); 48 | 49 | static cl::opt IFB("instruction-fetch-bandwidth", cl::desc("Specify the size of the reorder buffer. Default value is infinity"),cl::init(-1)); 50 | 51 | static cl::opt ReservationStation("reservation-station-size", cl::desc("Specify the size of a centralized reservation station. Default value is infinity"),cl::init(0)); 52 | 53 | static cl::opt ReorderBuffer("reorder-buffer-size", cl::desc("Specify the size of the reorder buffer. Default value is infinity"),cl::init(0)); 54 | 55 | static cl::opt LoadBuffer("load-buffer-size", cl::desc("Specify the size of the load buffer. Default value is infinity"),cl::init(0)); 56 | 57 | static cl::opt StoreBuffer("store-buffer-size", cl::desc("Specify the size of the store buffer. Default value is infinity"),cl::init(0)); 58 | 59 | static cl::opt LineFillBuffer("line-fill-buffer-size", cl::desc("Specify the size of the fill line buffer. Default value is infinity"),cl::init(0)); 60 | 61 | static cl::opt < bool > ReportOnlyPerformance("report-only-performance", cl::Hidden, cl::desc("Reports only performance (op count and span)"),cl::init(false)); 62 | 63 | static cl::opt TaskGraphFileName("taskgraph-file", cl::desc("File with Contech Task Graph"), cl::value_desc("filename")); 64 | -------------------------------------------------------------------------------- /backend/DynamicAnalysis/README: -------------------------------------------------------------------------------- 1 | Dynamic Analysis - Simulate a computer architecture for a sequence of LLVM IR instructions 2 | extracted from a Contech insturmented program and corresponding taskgraph 3 | 4 | See https://github.com/bprail/contech/wiki/Dynamic-Analysis for instructions on running 5 | the backend. 6 | 7 | Requires libboost-dev to build. 8 | -------------------------------------------------------------------------------- /backend/DynamicAnalysis/TBV.cpp: -------------------------------------------------------------------------------- 1 | #include "DynamicAnalysis.h" 2 | 3 | TBV::TBV() 4 | { 5 | //tbv_map.resize(SplitTreeRange); 6 | BitVector.resize(SplitTreeRange * MAX_RESOURCE_VALUE); 7 | e = true; 8 | } 9 | 10 | bool TBV::empty() 11 | { 12 | return e; 13 | } 14 | 15 | void TBV::insert_node(uint64_t key, unsigned bitPosition) 16 | { 17 | key = key % SplitTreeRange; 18 | e = false; 19 | //tbv_map[key].BitVector[bitPosition] = 1; 20 | BitVector[key * MAX_RESOURCE_VALUE + bitPosition] = 1; 21 | } 22 | 23 | void TBV::delete_node(uint64_t key, unsigned bitPosition) 24 | { 25 | key = key % SplitTreeRange; 26 | //tbv_map[key].BitVector[bitPosition] = 0; 27 | BitVector[key * MAX_RESOURCE_VALUE + bitPosition] = 0; 28 | } 29 | 30 | bool TBV::get_node(uint64_t key, unsigned bitPosition) 31 | { 32 | //if (empty()) return false; 33 | key = key % SplitTreeRange; 34 | //return (tbv_map[key].BitVector[bitPosition] == 1); 35 | return (BitVector[key * MAX_RESOURCE_VALUE + bitPosition] == 1); 36 | } 37 | 38 | bool TBV::get_node_nb(uint64_t key, unsigned bitPosition) 39 | { 40 | //if (empty()) return false; 41 | key = key % SplitTreeRange; 42 | //return (tbv_map[key].BitVector[bitPosition] == 0); 43 | return (BitVector[key * MAX_RESOURCE_VALUE + bitPosition] == 0); 44 | } 45 | 46 | uint64_t BitScan(vector< TBV> &FullOccupancyCyclesTree, uint64_t key, unsigned bitPosition) 47 | { 48 | uint64_t kLocal = key % SplitTreeRange; 49 | uint64_t chunk = kLocal / SplitTreeRange; 50 | 51 | while (chunk < FullOccupancyCyclesTree.size()) 52 | { 53 | while (kLocal < SplitTreeRange) 54 | { 55 | if (FullOccupancyCyclesTree[chunk].get_node(kLocal, bitPosition)) return (kLocal + chunk * SplitTreeRange); 56 | kLocal++; 57 | } 58 | kLocal = 0; 59 | chunk++; 60 | } 61 | 62 | return key; 63 | } 64 | -------------------------------------------------------------------------------- /backend/DynamicAnalysis/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import argparse 6 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 7 | import util 8 | import subprocess 9 | import shutil 10 | import tempfile 11 | 12 | def main(arg): 13 | # TODO: usage should be based on argparse 14 | if (len(arg)) == 1: 15 | print "Usage: {0} input\n".format(arg[0]) 16 | exit() 17 | 18 | parser = argparse.ArgumentParser(description="Runs dynamic analysis backend on benchmark") 19 | parser.add_argument("-b", "--bitcode", help="Bitcode file to analyze") 20 | parser.add_argument("-t", "--taskgraph", help="Taskgraph file to analyze") 21 | parser.add_argument("-o", default="output", help="Output directory") 22 | parser.add_argument("-n", default="65", help="Number of contexts to analyze") 23 | args = parser.parse_args() 24 | 25 | DynAnalysisLib = "-load=lib/LLVMDynAnalysis.so" 26 | ExecLatency = "-execution-units-latency={1,2,3,1,3,5,6,1,4,4,12,12,30,30,100,100}" 27 | ROBSize = "-reorder-buffer-size=168" 28 | LBSize = "-load-buffer-size=64" 29 | SBSize = "-store-buffer-size=36" 30 | CacheLineSize = "-cache-line-size=64" 31 | ILP = "-instruction-fetch-bandwidth=4" 32 | RSSize = "-reservation-station-size=56" 33 | L1Size = "-l1-cache-size=32768" 34 | L2Size = "-l2-cache-size=262144" 35 | LLCSize = "-llc-cache-size=20971520" 36 | ExecIssue = "-execution-units-parallel-issue={1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1}" 37 | ExecThru = "-execution-units-throughput={3,1,1,1,1,1,1,1,8,8,32,32,32,32,8,8}" 38 | FillBufSize = "-line-fill-buffer-size=10" 39 | WordSize = "-memory-word-size=8" 40 | AccessGran = "-mem-access-granularity={8,8,64,64,64,64,64,64}" 41 | 42 | # Assume that the taskgraph is formatted according to regress / util script convention 43 | benchName = args.taskgraph.split('/')[-1] 44 | b = benchName.split('.') 45 | 46 | if (b[0] == "splash2x"): 47 | benchName = b[1] 48 | else: 49 | benchName = b[0] 50 | 51 | try: 52 | os.makedirs(args.o + "/" + benchName) 53 | except os.error: 54 | #path already exists 55 | arg = arg 56 | 57 | for ctid in range(int(args.n)): 58 | filename = args.o + "/" + benchName + "/ct_{0}".format(ctid) 59 | ofile = tempfile.NamedTemporaryFile(suffix=".bc") 60 | with open(filename, "w") as of: 61 | #Use bash to expand arguments per https://stackoverflow.com/questions/8945826/expand-shell-path-expression-in-python 62 | util.pcall(["bash -c \" opt", DynAnalysisLib, "-EnginePass", args.bitcode, "-taskgraph-file=" + args.taskgraph, 63 | "-o " + ofile.name, "-context-number={0}".format(ctid), 64 | ExecLatency, ROBSize, LBSize, SBSize, CacheLineSize, ILP, RSSize, L1Size, 65 | L2Size, LLCSize, ExecIssue, ExecThru, FillBufSize, WordSize, AccessGran, "\""], 66 | outputFile=of, suppressOutput=False, silent=False) 67 | ofile.close() 68 | try: 69 | os.unlink(ofile.name) 70 | except os.error: 71 | # we expect that there will be an error returned by the unlink 72 | # The file should already be deleted, but we are calling just in case 73 | arg = arg 74 | 75 | if __name__ == "__main__": 76 | main(sys.argv) 77 | -------------------------------------------------------------------------------- /backend/DynamicCFG/.gitignore: -------------------------------------------------------------------------------- 1 | dynamicCFG 2 | -------------------------------------------------------------------------------- /backend/DynamicCFG/BasicBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | 3 | using namespace contech; 4 | 5 | BasicBlock::BasicBlock(uint32_t id) { this->id = id; this->runCount = 0; this->type = task_type_basic_blocks; } 6 | 7 | uint32_t BasicBlock::getID() { return id; } 8 | uint64_t BasicBlock::getRunCount() { return runCount; } 9 | vector BasicBlock::getSuccessors() { return successors; } 10 | void BasicBlock::addSuccessor(uint32_t id) { successors.push_back(id); } 11 | void BasicBlock::setRunCount(uint64_t count) { runCount = count; } 12 | void BasicBlock::incrementRunCount() { runCount++; } 13 | 14 | void BasicBlock::setNode(Agnode_t* node) { this->node = node; } 15 | Agnode_t* BasicBlock::getNode() { return node; } 16 | 17 | task_type BasicBlock::getType() { return type; } 18 | void BasicBlock::setType(task_type type) { this->type = type; } 19 | 20 | BasicBlock* BasicBlock::readBasicBlock(FILE* in) 21 | { 22 | if (feof(in) || ferror(in)) return NULL; 23 | uint32_t id; 24 | uint32_t typeInt; 25 | int succ1; 26 | int succ2; 27 | if (4 == fscanf(in, "%u,%u,%i,%i", &id, &typeInt, &succ1, &succ2)) 28 | { 29 | BasicBlock* b = new BasicBlock((uint32_t)id); 30 | b->setType((task_type)typeInt); 31 | if (succ1 != -1) b->addSuccessor((uint32_t)succ1); 32 | if (succ2 != -1) b->addSuccessor((uint32_t)succ2); 33 | return b; 34 | } else { 35 | return NULL; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /backend/DynamicCFG/BasicBlock.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../common/taskLib/Task.hpp" 3 | #include 4 | #include 5 | #include "graphviz/gvc.h" 6 | #include 7 | 8 | using namespace std; 9 | 10 | class BasicBlock 11 | { 12 | 13 | private: 14 | uint32_t id; 15 | uint64_t runCount; 16 | contech::task_type type; 17 | Agnode_t* node; 18 | vector successors; 19 | 20 | public: 21 | 22 | BasicBlock(uint32_t id); 23 | 24 | uint32_t getID(); 25 | 26 | uint64_t getRunCount(); 27 | void setRunCount(uint64_t count); 28 | void incrementRunCount(); 29 | 30 | contech::task_type getType(); 31 | void setType(contech::task_type type); 32 | 33 | void setNode(Agnode_t* node); 34 | Agnode_t* getNode(); 35 | 36 | vector getSuccessors(); 37 | void addSuccessor(uint32_t id); 38 | 39 | static BasicBlock* readBasicBlock(FILE* in); 40 | }; 41 | -------------------------------------------------------------------------------- /backend/DynamicCFG/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -O3 -std=c++11 3 | OBJECTS= dynamicCFG.o BasicBlock.o 4 | INCLUDES= -I. 5 | LIBS= -L/net/tinker/local/lib64 -L/net/tinker/local/lib -L../../common/taskLib/ -lgvc -lcgraph -lTask -L../CommTracker/ -lCommTracker -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | EXTERNALS= 7 | 8 | all: taskLib dynamicCFG 9 | 10 | taskLib: 11 | make -C ../../common/taskLib 12 | 13 | %.o : %.cpp 14 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 15 | dynamicCFG : $(OBJECTS) 16 | $(CXX) $^ $(CXXFLAGS) $(LIBS) $(EXTERNALS) -o $@ 17 | 18 | clean: 19 | rm -f *.o 20 | rm -f dynamicCFG 21 | -------------------------------------------------------------------------------- /backend/DynamicCFG/output/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | -------------------------------------------------------------------------------- /backend/EasyProf/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -std=c++11 -O3 3 | OBJECT_PROF= easyProf.o 4 | OBJECT_VIZ= easyViz.o 5 | INCLUDES= 6 | LIBS= -L/net/tinker/local/lib64 -L/net/tinker/local/lib -lgvc -lcgraph -L../../common/taskLib -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 7 | 8 | all: taskLib easyProf easyViz 9 | 10 | taskLib: 11 | make -C ../../common/taskLib 12 | 13 | %.o : %.cpp 14 | $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< 15 | 16 | easyProf: $(OBJECT_PROF) 17 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) 18 | 19 | easyViz: $(OBJECT_VIZ) 20 | $(CXX) $^ $(CXXFLAGS) $(LIBS) -o $@ $(EXTERNALS) 21 | 22 | clean: 23 | rm -f *.o 24 | rm -f easyProf easyViz 25 | -------------------------------------------------------------------------------- /backend/EasyProf/README: -------------------------------------------------------------------------------- 1 | EasyProf is a light-weight profiling tool built on top of Contech. 2 | It's intended to profile OpenMPI applications and give insights to 3 | programmers about how they could further optimize their parallel code. 4 | However, due to limitations of current version of Contech, our 5 | implementations works better with other parallel computing 6 | frameworks (OpenMP, pthreads, etc.) 7 | 8 | - alphalzh 9 | -------------------------------------------------------------------------------- /backend/EasyProf/usage: -------------------------------------------------------------------------------- 1 | ## EasyProf: An easy-to-use parallel application profiling toolkit based on Contech 2 | We implemented EasyProf (formerly named EasyMPI), a light-weight profiler tool for parallel applications built on top of frameworks like pthread, cilk and OpenMP. This project is based on [Contech](https://github.com/bprail/contech), an instrumentation framework for parallel computing developed by B. P. Railing et al. 3 | 4 | ### Introduction 5 | Performance is always one of the most important aspects to consider in terms of parallel application design. However, it's often non-trivial to measure a parallel application's performance and figure out the bottlenecks. Therefore, we decide to build a profiling tool that can help programmers learn more about their parallel applications' performance. 6 | 7 | We implemented our profiling tool on top of Contech, an instrumentation framework which is capable of collecting traces from parallel applications and generating task graphs from the collected trace. Such task graphs can then be processed by various "backends" to yield useful profiling results. EasyProf can be regarded as a powerful backend for Contech such that given a task graph file generated by running a Contech-instrumented executable, it can provide detailed statistics and useful information such as visualization of the task graph, work imbalance across multiple execution contexts, total time spent on synchronization, etc. to the programmer. 8 | 9 | ### How to build EasyProf 10 | **Please ensure C++ 11 is supported by your compiler.** If you use g++, it requires a minimum version of 4.8. 11 | Enter the directory contech/backends/EasyProf and just hit make to do the work! 12 | 13 | ### How to use EasyProf 14 | After successfully compile the code, run ./easyProf taskGraphInputFile to run the profiler, and ./easyViz taskGraphInputFile to run the visualizer. You can play with the task graph files we included in the /taskgraphs directory! 15 | 16 | You may have to wait a while for the profiler to work. It will display information on screen about the current processing progress. After it finished processing the task graph, you will be prompted to input command. 17 | 18 | Available commands includes: 19 | * stat (show basic statistics about the program) 20 | * mem [show information about memory usage] 21 | * main [show information about main execution context (or main thread)] 22 | * group [show information about execution context group (or parallelized threads)] 23 | * g{groupId} [show information about specific context group. Example: g3] 24 | * c{contextId} [show information about specific context. Example: c7] 25 | * quit [quit EasyProf] 26 | 27 | For detailed information about the profiler, e.g. what statistics it can generate, please refer to the final report linked below. 28 | 29 | ### Demo 30 | The project will be demoed at the poster session on December 12th. An MPI program will be profiled by the profiler, and we will show how it can help the programmers optimize their code based on the profiling result. 31 | 32 | Screenshots of actual runs: 33 | ![Image of screen 1](https://github.com/alphalzh/EasyMPI/blob/master/doc/s1.png?raw=true) 34 | ![Image of screen 2](https://github.com/alphalzh/EasyMPI/blob/master/doc/s2.png?raw=true) 35 | Generated task graph: 36 | ![Image of taskgraph](https://github.com/alphalzh/EasyMPI/blob/master/doc/compressGraph.png?raw=true) 37 | 38 | ### Proposal 39 | Please click [here](https://github.com/alphalzh/EasyMPI/blob/master/doc/Proposal.pdf) for the project proposal. 40 | 41 | ### Checkpoint Report 42 | Please click [here](https://github.com/alphalzh/EasyMPI/blob/master/doc/Project_Checkpoint_zihengl_xingyuj1.pdf) for the project checkpoint report. 43 | 44 | ### Final Report 45 | Please click [here](https://github.com/alphalzh/EasyMPI/blob/master/doc/EasyProf_final_report.pdf) for the project's final report. 46 | -------------------------------------------------------------------------------- /backend/Harmony/.gitignore: -------------------------------------------------------------------------------- 1 | harmony 2 | -------------------------------------------------------------------------------- /backend/Harmony/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | PROJECT = harmony 3 | OBJECTS = main.o 4 | #TEST_PROJECT = lockAnalysis_test 5 | #TEST_OBJECTS = ct_event_mock.o LockAnalysis.o lockAnalysis_test.o 6 | CPPFLAGS = -O3 -g --std=c++11 7 | LIBS = -lct_event -L../../common/eventLib/ -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 8 | 9 | all: $(PROJECT) 10 | 11 | $(PROJECT): $(OBJECTS) 12 | $(CXX) $(OBJECTS) $(LIBS) -o $(PROJECT) 13 | 14 | #ct_event_mock.o: 15 | # $(CXX) -O3 -g -c -o ct_event_mock.o ct_event_mock.c 16 | 17 | #test: $(TEST_OBJECTS) 18 | # $(CXX) $(TEST_OBJECTS) -o $(TEST_PROJECT) 19 | # ./lockAnalysis_test 20 | 21 | clean: 22 | rm -f $(PROJECT) $(OBJECTS) 23 | # rm -f $(TEST_PROJECT) $(TEST_OBJECTS) 24 | 25 | 26 | -------------------------------------------------------------------------------- /backend/Harmony/README: -------------------------------------------------------------------------------- 1 | Harmony - This backend reproduces the results generated by the Harmony tool, 2 | Harmony: collection and analysis of parallel block vectors, ISCA 2012. The 3 | binary analyzes a task graph and produces a csv output. The python script 4 | generates heat maps from the csv output. 5 | 6 | -------------------------------------------------------------------------------- /backend/Heltech/.gitignore: -------------------------------------------------------------------------------- 1 | heltech 2 | -------------------------------------------------------------------------------- /backend/Heltech/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -std=c++11 -O3 -g 3 | OBJECTS= heltech.o 4 | INCLUDES= -I. 5 | LIBS= -L/net/tinker/local/lib64 -L/net/tinker/local/lib -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | EXTERNALS= 7 | 8 | all: taskLib heltech 9 | 10 | taskLib: 11 | make -C ../../common/taskLib 12 | 13 | %.o : %.cpp 14 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 15 | heltech: $(OBJECTS) 16 | $(CXX) $^ $(CXXFLAGS) $(LIBS) -o $@ $(EXTERNALS) 17 | 18 | clean: 19 | rm -f *.o 20 | rm -f heltech 21 | -------------------------------------------------------------------------------- /backend/Heltech/README: -------------------------------------------------------------------------------- 1 | Heltech - This backend mimics the behavior of the Valgrind backend, Helgrind. 2 | These analysis tools attempt to identify data races. Heltech uses a Contech 3 | task graph to identify the last write to any virtual address and checks 4 | whether subsequent accesses have an ordering using the task dependencies. 5 | 6 | -------------------------------------------------------------------------------- /backend/Heltech/heltech.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HELTECH_HPP 2 | #define HELTECH_HPP 3 | 4 | #include "../../common/taskLib/TaskGraph.hpp" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | void hbRaceDetector(FILE* taskGraphIn); 15 | 16 | void addTaskToGraphMap(unordered_map >& graphMap, contech::Task* t); 17 | bool hbPathExists(unordered_map >& graphMap, contech::TaskId start, contech::TaskId end); 18 | void reportRace(contech::MemoryAction existingMop, 19 | contech::MemoryAction newMop, 20 | contech::TaskId existingTID, 21 | contech::TaskId newTID, 22 | contech::BasicBlockAction bb, 23 | unsigned int, 24 | int idx, 25 | contech::TaskGraphInfo*); 26 | 27 | //Simple container class to bind a memory action and an CTID 28 | class Heltech_memory_op { 29 | public: 30 | Heltech_memory_op(contech::MemoryAction mop, unsigned int, contech::TaskId tid); 31 | Heltech_memory_op(); 32 | contech::MemoryAction mop; 33 | unsigned int bbid; 34 | contech::TaskId tid; 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /backend/MemUse/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = memUse 2 | CXX=g++ 3 | CXXFLAGS= -g -std=c++11 -O3 4 | OBJECTS= main.o 5 | LPROJ = libmemUse.a 6 | LOBJ = memUse.o 7 | INCLUDES= 8 | LIBS= -L../../common/taskLib/ -lTask -lz -L. -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 9 | EXTERNALS= 10 | 11 | all: taskLib $(LPROJ) $(PROJECT) 12 | 13 | taskLib: 14 | $(MAKE) -C ../../common/taskLib 15 | 16 | %.o : %.cpp 17 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 18 | $(PROJECT): $(OBJECTS) $(LOBJ) 19 | $(CXX) -o $(PROJECT) $(OBJECTS) $(CXXFLAGS) $(LIBS) -l$(PROJECT) 20 | 21 | $(LPROJ): $(LOBJ) 22 | ar rc $(LPROJ) $(LOBJ) 23 | 24 | clean: 25 | rm -f *.o 26 | rm -f $(PROJECT) 27 | -------------------------------------------------------------------------------- /backend/MemUse/README: -------------------------------------------------------------------------------- 1 | MemUse - Memory Usage Backend 2 | 3 | This backend analyzes the memory used in a taskgraph, specifically identifying 4 | quantity of heap versus stack space used. It utilizes the malloc / free 5 | actions, as well as creates a map of virtual address space from the memory 6 | actions. 7 | -------------------------------------------------------------------------------- /backend/MemUse/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../../common/taskLib/Backend.hpp" 2 | #include "memUse.hpp" 3 | 4 | using namespace contech; 5 | 6 | int main(int argc, char** argv) 7 | { 8 | if (argc == 1) 9 | { 10 | fprintf(stderr, "Usage: %s \n", argv[0]); 11 | return 1; 12 | } 13 | 14 | BackendMemUse* bmu = new BackendMemUse(); 15 | SimpleBackendWrapper* sbw = new SimpleBackendWrapper(argv[1], bmu); 16 | 17 | sbw->runBackend(); 18 | sbw->completeRun(stdout); 19 | delete sbw; 20 | delete bmu; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /backend/MemUse/memUse.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MEM_USE_HPP 2 | #define MEM_USE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../../common/taskLib/TaskGraph.hpp" 8 | #include "../../common/taskLib/Backend.hpp" 9 | 10 | class BackendMemUse : public contech::Backend { 11 | 12 | private: 13 | struct malloc_stats { 14 | uint32_t alloc_count; 15 | uint32_t free_count; 16 | }; 17 | 18 | struct track_stats { 19 | uint32_t size; 20 | uint32_t hits; 21 | }; 22 | uint32_t seqAllocCurrent, seqAllocMax; 23 | uint32_t seqFreeCurrent, seqFreeMax; 24 | uint64_t totalAllocSize, effAllocSize; 25 | uint64_t maxWorkSet, currWorkSet; 26 | uint64_t stackSize; 27 | std::map sizeStats; 28 | std::map sizeOfAlloc; 29 | std::map sizeOfAllocNoErase; 30 | std::map stackAlloc; 31 | std::map refCountPlus; // If more than 1 ref to address exist 32 | 33 | public: 34 | void resetBackend(); 35 | void updateBackend(contech::Task*); 36 | void completeBackend(FILE*, contech::TaskGraphInfo*); 37 | BackendMemUse(); 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /backend/MemUse/memuse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.colors as colors 15 | import matplotlib as matplotlib 16 | import json 17 | import math 18 | import csv 19 | 20 | def makeUnit(v): 21 | unit = "B" 22 | if (v > 10000): 23 | v /= 1024 24 | unit = "KB" 25 | if (v > 10000): 26 | v /= 1024 27 | unit = "MB" 28 | if (v > 10000): 29 | v /= 1024 30 | unit = "GB" 31 | v = int(v) 32 | return str(v) + unit 33 | 34 | def main(arg): 35 | if (len(arg)) == 1: 36 | print "Usage: {0} input\n".format(arg[0]) 37 | exit() 38 | 39 | p = 1 40 | for harmony_in in arg[1:]: 41 | 42 | # try: 43 | with open(harmony_in, "r") as csvfile: 44 | #sorry to use blah, but I blanked on a name for this latest temp 45 | blah = csv.reader(csvfile) 46 | rowNum = 0 47 | meanSize = 0 48 | totalAlloc = 0 49 | sizeList = [] 50 | freqList = [] 51 | for row in blah: 52 | if (rowNum == 0): 53 | stats = [] 54 | for v in row[1:-1]: 55 | stats.append(makeUnit(int(v))) 56 | #stats = row[1:] 57 | stats.append(str(100.0*float(row[-1]))) 58 | rowNum += 1 59 | continue 60 | if (len(row) < 3): 61 | rowNum += 1 62 | continue 63 | 64 | r = map(int, row) 65 | size = r[0] 66 | numAlloc = r[1] 67 | meanSize += size 68 | totalAlloc += numAlloc 69 | sizeList.append( size) 70 | freqList.append(numAlloc) 71 | 72 | if (rowNum == 0): 73 | continue 74 | 75 | if (totalAlloc > 0): 76 | meanSize = meanSize / totalAlloc 77 | medianNum = (totalAlloc + 1) / 2 78 | pos = 0 79 | count = 0 80 | for a in sizeList: 81 | count += freqList[pos] 82 | if (count >= medianNum): 83 | medianSize = a 84 | break 85 | pos += 1 86 | 87 | harmony_l = harmony_in.split('/') 88 | harmony_in = harmony_l[-1] 89 | harmony_l = harmony_in.split('.') 90 | harmony_in = harmony_l[-2] 91 | pstr = harmony_in 92 | pstats = ','.join(s for s in stats) 93 | meanStr = makeUnit(meanSize) 94 | medianStr = makeUnit(medianSize) 95 | pstr = pstr + "," + pstats + ", {0}, {1}".format(meanStr, medianStr) 96 | print pstr 97 | 98 | if __name__ == "__main__": 99 | main(sys.argv) 100 | -------------------------------------------------------------------------------- /backend/RemSync/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -std=c++11 -O3 3 | OBJECTS= remSync.o 4 | INCLUDES= 5 | LIBS= -L../../common/taskLib -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | 7 | all: taskLib remSync 8 | 9 | taskLib: 10 | make -C ../../common/taskLib 11 | 12 | %.o : %.cpp 13 | $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< 14 | remSync: $(OBJECTS) 15 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) 16 | 17 | clean: 18 | rm -f *.o 19 | rm -f remSync 20 | -------------------------------------------------------------------------------- /backend/RemSync/README.txt: -------------------------------------------------------------------------------- 1 | RemSync - Remove Sync was a prototype backend that demonstrated graph 2 | modification through identifying sequences of critical sections 3 | that had no intervening contexts. 4 | 5 | This backend is not up to date and is deprecated. 6 | -------------------------------------------------------------------------------- /backend/SCacheOrder/.gitignore: -------------------------------------------------------------------------------- 1 | scache 2 | -------------------------------------------------------------------------------- /backend/SCacheOrder/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = scache 2 | CXX=g++ 3 | CXXFLAGS= -g -std=c++11 -O3 4 | OBJECTS= main.o simpleCache.o TraceWrapper.o 5 | INCLUDES= -I../../common/taskLib/ 6 | LIBS= -L../../common/taskLib/ -lTask -lz -L. -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 7 | EXTERNALS= 8 | 9 | all: taskLib $(PROJECT) 10 | 11 | taskLib: 12 | $(MAKE) -C ../../common/taskLib 13 | 14 | %.o : %.cpp 15 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 16 | $(PROJECT): $(OBJECTS) 17 | $(CXX) -o $(PROJECT) $(OBJECTS) $(CXXFLAGS) $(LIBS) 18 | 19 | clean: 20 | rm $(OBJECTS) $(PROJECT) 21 | 22 | -------------------------------------------------------------------------------- /backend/SCacheOrder/TraceWrapper.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TRACEWRAPPER_HPP 2 | #define TRACEWRAPPER_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct MemReq{ 12 | unsigned int ctid; 13 | bool isWrite; 14 | char numOfBytes; 15 | unsigned long int address; 16 | unsigned int bbid; 17 | }; 18 | 19 | typedef struct _ctid_current_state 20 | { 21 | bool blocked; // is this task running or blocked? 22 | bool terminated; // has this task terminated 23 | contech::ct_timestamp taskCurrTime; // all events before this time have been processed 24 | contech::ct_timestamp taskRate; // how many cycles does basic block take on average 25 | contech::Task* currentTask; // pointer to task being processed 26 | contech::TaskId nextTaskId; // next task id in this contech id 27 | contech::Task::basicBlockActionCollection::iterator currentBB; //current basic block to next be processed 28 | contech::Task::basicBlockActionCollection currentBBCol; //hold the basic block collection for the end iterator 29 | } ctid_current_state, *pctid_current_state; 30 | 31 | class MemReqContainer 32 | { 33 | public: 34 | contech::ct_timestamp reqTime; 35 | vector mav; 36 | unsigned int bbid; 37 | unsigned int ctid; 38 | //unsigned int pushedOps; 39 | 40 | bool operator()( MemReqContainer &t1, MemReqContainer &t2) 41 | { 42 | return t1.reqTime > t2.reqTime; 43 | } 44 | }; 45 | 46 | class TraceWrapper 47 | { 48 | public: 49 | TraceWrapper(char*); 50 | ~TraceWrapper(); 51 | 52 | contech::Task* pauseTask; 53 | contech::ct_timestamp priorStart; 54 | contech::TaskGraph* tg; 55 | contech::ct_timestamp lastOpTime; 56 | std::priority_queue , MemReqContainer> memReqQ; 57 | map contechState; 58 | 59 | int populateQueue(); 60 | contech::TaskId getSequenceTask(vector& succ, contech::ContextId selfId); 61 | 62 | int getNextMemoryRequest(MemReqContainer&); 63 | }; 64 | 65 | #endif -------------------------------------------------------------------------------- /backend/SCacheOrder/main.cpp: -------------------------------------------------------------------------------- 1 | #include "simpleCache.hpp" 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | if (argc < 2) 7 | { 8 | fprintf(stderr, "%s \n", argv[0]); 9 | return 1; 10 | } 11 | 12 | #if 0 13 | if (argc == 3) 14 | { 15 | SimpleCacheBackend* bsc = new SimpleCacheBackend(atoi(argv[1]), 2, 1); 16 | contech::SimpleBackendWrapper* sbw = new contech::SimpleBackendWrapper(argv[2], bsc); 17 | 18 | sbw->runBackend(); 19 | sbw->completeRun(stdout); 20 | delete sbw; 21 | delete bsc; 22 | } 23 | else 24 | { 25 | for (int c = 10; c <= 28; c++) 26 | { 27 | SimpleCacheBackend* bsc = new SimpleCacheBackend(c, 2, 0); 28 | contech::SimpleBackendWrapper* sbw = new contech::SimpleBackendWrapper(argv[1], bsc); 29 | 30 | sbw->runBackend(); 31 | sbw->completeRun(stdout); 32 | delete sbw; 33 | delete bsc; 34 | } 35 | } 36 | 37 | #endif 38 | if (argc == 3) 39 | { 40 | TraceWrapper* tw = new TraceWrapper(argv[2]); 41 | SimpleCacheBackend* bsc = new SimpleCacheBackend(atoi(argv[1]), 2, 1); 42 | MemReqContainer mrc; 43 | 44 | while (tw->getNextMemoryRequest(mrc)) 45 | { 46 | bsc->updateBackend(mrc); 47 | } 48 | 49 | bsc->completeBackend(stdout, tw->tg->getTaskGraphInfo()); 50 | delete bsc; 51 | delete tw; 52 | } 53 | else 54 | { 55 | for (int c = 10; c <= 28; c++) 56 | { 57 | TraceWrapper tw(argv[1]); 58 | SimpleCacheBackend bsc(c, 2, 0); 59 | 60 | MemReqContainer mrc; 61 | while (tw.getNextMemoryRequest(mrc)) 62 | { 63 | bsc.updateBackend(mrc); 64 | } 65 | 66 | bsc.completeBackend(stdout, tw.tg->getTaskGraphInfo()); 67 | fflush(stdout); 68 | } 69 | 70 | #if 0 71 | TraceWrapper* tw; 72 | 73 | MemReqContainer mrc; 74 | int c_start = 10, c_end = 29, c_pt; 75 | 76 | while (c_start < c_end) 77 | { 78 | vector scbv; 79 | tw = new TraceWrapper(argv[1]); 80 | 81 | c_pt = c_start + 2; 82 | if (c_pt > c_end) c_pt = c_end; 83 | 84 | for (int c = c_start; c < c_pt; c++) 85 | { 86 | //printf("", c); 87 | //fflush(stdout); 88 | SimpleCacheBackend* bsc = new SimpleCacheBackend(c, 2, 0); 89 | scbv.push_back(bsc); 90 | } 91 | 92 | while (tw->getNextMemoryRequest(mrc)) 93 | { 94 | for (auto bsc : scbv) 95 | { 96 | bsc->updateBackend(mrc); 97 | } 98 | } 99 | 100 | for (auto bsc : scbv) 101 | { 102 | bsc->completeBackend(stdout, tw->tg->getTaskGraphInfo()); 103 | delete bsc; 104 | } 105 | fflush(stdout); 106 | 107 | c_start += 2; 108 | delete tw; 109 | } 110 | #endif 111 | } 112 | 113 | return 0; 114 | } -------------------------------------------------------------------------------- /backend/SCacheOrder/plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.colors as colors 15 | import matplotlib as matplotlib 16 | import json 17 | import math 18 | import csv 19 | 20 | def main(arg): 21 | if (len(arg)) == 1: 22 | print "Usage: {0} input\n".format(arg[0]) 23 | exit() 24 | 25 | p = 1 26 | fig = plt.figure(figsize=(7, 7)) 27 | for file_in in arg[1:]: 28 | 29 | avg = [] 30 | # try: 31 | with open(file_in, "r") as csvfile: 32 | #sorry to use blah, but I blanked on a name for this latest temp 33 | dialect = csv.excel 34 | dialect.skipinitialspace = True 35 | blah = csv.reader(csvfile, dialect=dialect) 36 | 37 | for row in blah: 38 | r = map(float, row) 39 | avg.append(100.0*r[0]) 40 | 41 | if (len(avg) == 0): 42 | continue 43 | print len(avg) 44 | if (p <= 28): 45 | if (len(arg) == 2): 46 | ax = plt.subplot(1,1, p) 47 | else: 48 | ax = plt.subplot(7,4, p) 49 | #ax = plt.subplot(2,2, p) 50 | #plt.ylim(0,24) 51 | box = ax.get_position() 52 | ax.set_position([box.x0, box.y0, box.width, box.height*0.8]) 53 | x_val = range(0, (len(avg))) 54 | x_val_exp = [] 55 | for x in x_val: 56 | x_val_exp.append(math.pow(2, x+10)) 57 | plt.plot(x_val_exp, avg) 58 | if (len(arg) == 2): 59 | plt.xticks(fontsize=12) 60 | plt.yticks(fontsize=12) 61 | plt.rc('font', size=12) 62 | else: 63 | plt.xticks(fontsize=5) 64 | plt.yticks(fontsize=5) 65 | plt.rc('font', size=5) 66 | ax.set_xscale('log', basex=2) 67 | #plt.ticklabel_format(axis='x', style='plain') 68 | for tick in ax.xaxis.get_major_ticks(): 69 | tick.label.set_rotation('vertical') 70 | 71 | if 0 == 1: 72 | #Approach 2 - Project points based on a uniformly decreasing line 73 | ideal_m = (avg[-1] - avg[0]) / len(avg) 74 | culum = avg[0] 75 | proj = [] 76 | for a in avg: 77 | proj.append(a - culum) 78 | culum += ideal_m 79 | accel = [] 80 | last = 0 81 | for pr in proj: 82 | accel.append(pr - last) 83 | last = pr 84 | #plt.plot(range(10,10 + (len(avg))), proj) 85 | #plt.plot(range(10,10 + (len(avg))), accel) 86 | i = 0 87 | last = 0 88 | first_green = 0 89 | first_red = 0 90 | for a in accel: 91 | if i == 0: 92 | i += 1 93 | last = a 94 | continue 95 | if last / a < 0: #is last > 0 and a < 0 or vis versa 96 | if (a > 0): 97 | c = 'r' 98 | if (first_red == 0): 99 | first_red = i 100 | else: 101 | c = 'g' 102 | if (first_green == 0): 103 | first_green = i 104 | # plt.axvline(i - 1 + 10, linewidth=1.25, color=c) 105 | last = a 106 | i += 1 107 | 108 | arrow_pt = 0 109 | if (first_green == 0 or first_red < first_green): 110 | arrow_pt = first_red 111 | else: 112 | arrow_pt = first_green 113 | 114 | if (arrow_pt < 3): 115 | arrow_pt = 3 116 | arrow_val = avg[arrow_pt] 117 | arrow_pt = math.pow(2, arrow_pt) 118 | 119 | plt.arrow(arrow_pt, arrow_val, arrow_pt, arrow_val + 1) 120 | plt.axvline(arrow_pt, linewidth=1.25, color='r') 121 | 122 | harmony_l = file_in.split('/') 123 | file_in = harmony_l[-1] 124 | harmony_l = file_in.split('.') 125 | file_in = harmony_l[-2] 126 | plt.title(file_in, fontsize=5) 127 | p += 1 128 | # plt.subplots_adjust(left=0.1, right =(0.1*max_threads)) 129 | plt.savefig( "temp.pdf") 130 | plt.savefig( "temp.png") 131 | 132 | 133 | if __name__ == "__main__": 134 | main(sys.argv) -------------------------------------------------------------------------------- /backend/SCacheOrder/simpleCache.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLECACHE_HPP 2 | #define SIMPLECACHE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "TraceWrapper.hpp" 10 | 11 | struct cache_stats_t { 12 | uint64_t accesses; 13 | uint64_t misses; 14 | }; 15 | 16 | class SimpleCache 17 | { 18 | struct cache_line 19 | { 20 | uint64_t tag; 21 | uint64_t lastAccess; 22 | bool dirty; 23 | char valid_bits; 24 | }; 25 | 26 | uint64_t read_misses; 27 | uint64_t write_misses; 28 | uint64_t accesses; 29 | 30 | std::vector< std::deque > cacheBlocks; 31 | 32 | bool updateCacheLine(uint64_t idx, uint64_t tag, uint64_t offset, uint64_t num, bool); 33 | void printIndex(uint64_t idx); 34 | 35 | public: 36 | 37 | uint64_t global_c; 38 | static const uint64_t global_b = 6; 39 | uint64_t global_s; 40 | 41 | SimpleCache(); 42 | SimpleCache(uint64_t, uint64_t); 43 | double getMissRate(); 44 | bool updateCache(bool rw, char numOfBytes, uint64_t address, cache_stats_t* p_stats); 45 | }; 46 | 47 | struct mallocStats 48 | { 49 | uint32_t bbid; 50 | uint32_t size; 51 | uint32_t misses; 52 | }; 53 | 54 | class SimpleCacheBackend : public contech::Backend 55 | { 56 | SimpleCache* sharedCache; 57 | std::map contextCacheState; 58 | std::map basicBlockMisses; 59 | std::map allocBlocks; 60 | cache_stats_t* p_stats; 61 | bool printMissLines; 62 | 63 | public: 64 | virtual void resetBackend(); 65 | virtual void updateBackend(contech::Task*); 66 | virtual void updateBackend(MemReqContainer&); 67 | virtual void completeBackend(FILE*, contech::TaskGraphInfo*); 68 | 69 | SimpleCacheBackend(uint64_t c, uint64_t s, int printMissLoc); 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /backend/SimpleCache/.gitignore: -------------------------------------------------------------------------------- 1 | output* 2 | scache 3 | -------------------------------------------------------------------------------- /backend/SimpleCache/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = scache 2 | CXX=g++ 3 | CXXFLAGS= -g -std=c++11 -O3 4 | OBJECTS= main.o simpleCache.o 5 | INCLUDES= -I../../common/taskLib/ 6 | LIBS= -L../../common/taskLib/ -lTask -lz -L. -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 7 | EXTERNALS= 8 | 9 | all: taskLib $(PROJECT) 10 | 11 | taskLib: 12 | $(MAKE) -C ../../common/taskLib 13 | 14 | %.o : %.cpp 15 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 16 | $(PROJECT): $(OBJECTS) 17 | $(CXX) -o $(PROJECT) $(OBJECTS) $(CXXFLAGS) $(LIBS) 18 | 19 | clean: 20 | rm $(OBJECTS) $(PROJECT) 21 | 22 | -------------------------------------------------------------------------------- /backend/SimpleCache/main.cpp: -------------------------------------------------------------------------------- 1 | #include "simpleCache.hpp" 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | if (argc < 2) 7 | { 8 | fprintf(stderr, "%s \n", argv[0]); 9 | return 1; 10 | } 11 | 12 | if (argc == 3) 13 | { 14 | SimpleCacheBackend* bsc = new SimpleCacheBackend(atoi(argv[1]), 2, 1); 15 | contech::SimpleBackendWrapper* sbw = new contech::SimpleBackendWrapper(argv[2], bsc); 16 | 17 | sbw->runBackend(); 18 | sbw->completeRun(stdout); 19 | delete sbw; 20 | delete bsc; 21 | } 22 | else 23 | { 24 | for (int c = 10; c <= 28; c++) 25 | { 26 | SimpleCacheBackend* bsc = new SimpleCacheBackend(c, 2, 0); 27 | contech::SimpleBackendWrapper* sbw = new contech::SimpleBackendWrapper(argv[1], bsc); 28 | 29 | sbw->runBackend(); 30 | sbw->completeRun(stdout); 31 | delete sbw; 32 | delete bsc; 33 | } 34 | } 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /backend/SimpleCache/plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.colors as colors 15 | import matplotlib as matplotlib 16 | import json 17 | import math 18 | import csv 19 | 20 | def main(arg): 21 | if (len(arg)) == 1: 22 | print "Usage: {0} input\n".format(arg[0]) 23 | exit() 24 | 25 | p = 1 26 | fig = plt.figure(figsize=(7, 7)) 27 | for file_in in arg[1:]: 28 | 29 | avg = [] 30 | # try: 31 | with open(file_in, "r") as csvfile: 32 | #sorry to use blah, but I blanked on a name for this latest temp 33 | dialect = csv.excel 34 | dialect.skipinitialspace = True 35 | blah = csv.reader(csvfile, dialect=dialect) 36 | 37 | for row in blah: 38 | r = map(float, row) 39 | avg.append(100.0*r[0]) 40 | 41 | if (len(avg) == 0): 42 | continue 43 | print len(avg) 44 | if (p <= 28): 45 | if (len(arg) == 2): 46 | ax = plt.subplot(1,1, p) 47 | else: 48 | ax = plt.subplot(7,4, p) 49 | #ax = plt.subplot(2,2, p) 50 | #plt.ylim(0,24) 51 | box = ax.get_position() 52 | ax.set_position([box.x0, box.y0, box.width, box.height*0.8]) 53 | x_val = range(0, (len(avg))) 54 | x_val_exp = [] 55 | for x in x_val: 56 | x_val_exp.append(math.pow(2, x)) 57 | plt.plot(x_val_exp, avg) 58 | if (len(arg) == 2): 59 | plt.xticks(fontsize=12) 60 | plt.yticks(fontsize=12) 61 | plt.rc('font', size=12) 62 | else: 63 | plt.xticks(fontsize=5) 64 | plt.yticks(fontsize=5) 65 | plt.rc('font', size=5) 66 | ax.set_xscale('log', basex=2) 67 | plt.ticklabel_format(axis='x', style='plain') 68 | for tick in ax.xaxis.get_major_ticks(): 69 | tick.label.set_rotation('vertical') 70 | 71 | #Approach 2 - Project points based on a uniformly decreasing line 72 | ideal_m = (avg[-1] - avg[0]) / len(avg) 73 | culum = avg[0] 74 | proj = [] 75 | for a in avg: 76 | proj.append(a - culum) 77 | culum += ideal_m 78 | accel = [] 79 | last = 0 80 | for pr in proj: 81 | accel.append(pr - last) 82 | last = pr 83 | #plt.plot(range(10,10 + (len(avg))), proj) 84 | #plt.plot(range(10,10 + (len(avg))), accel) 85 | i = 0 86 | last = 0 87 | first_green = 0 88 | first_red = 0 89 | for a in accel: 90 | if i == 0: 91 | i += 1 92 | last = a 93 | continue 94 | if last / a < 0: #is last > 0 and a < 0 or vis versa 95 | if (a > 0): 96 | c = 'r' 97 | if (first_red == 0): 98 | first_red = i 99 | else: 100 | c = 'g' 101 | if (first_green == 0): 102 | first_green = i 103 | # plt.axvline(i - 1 + 10, linewidth=1.25, color=c) 104 | last = a 105 | i += 1 106 | 107 | arrow_pt = 0 108 | if (first_green == 0 or first_red < first_green): 109 | arrow_pt = first_red 110 | else: 111 | arrow_pt = first_green 112 | 113 | if (arrow_pt < 3): 114 | arrow_pt = 3 115 | arrow_val = avg[arrow_pt] 116 | arrow_pt = math.pow(2, arrow_pt) 117 | 118 | plt.arrow(arrow_pt, arrow_val, arrow_pt, arrow_val + 1) 119 | plt.axvline(arrow_pt, linewidth=1.25, color='r') 120 | 121 | harmony_l = file_in.split('/') 122 | file_in = harmony_l[-1] 123 | harmony_l = file_in.split('.') 124 | file_in = harmony_l[-2] 125 | plt.title(file_in, fontsize=5) 126 | p += 1 127 | # plt.subplots_adjust(left=0.1, right =(0.1*max_threads)) 128 | plt.savefig( "temp.pdf") 129 | plt.savefig( "temp.png") 130 | 131 | 132 | if __name__ == "__main__": 133 | main(sys.argv) -------------------------------------------------------------------------------- /backend/SimpleCache/simpleCache.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLECACHE_HPP 2 | #define SIMPLECACHE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct cache_stats_t { 10 | uint64_t accesses; 11 | uint64_t misses; 12 | }; 13 | 14 | class SimpleCache 15 | { 16 | struct cache_line 17 | { 18 | uint64_t tag; 19 | uint64_t lastAccess; 20 | bool dirty; 21 | char valid_bits; 22 | }; 23 | 24 | uint64_t read_misses; 25 | uint64_t write_misses; 26 | uint64_t accesses; 27 | 28 | std::vector< std::deque > cacheBlocks; 29 | 30 | bool updateCacheLine(uint64_t idx, uint64_t tag, uint64_t offset, uint64_t num, bool); 31 | void printIndex(uint64_t idx); 32 | 33 | public: 34 | SimpleCache(); 35 | double getMissRate(); 36 | bool updateCache(bool rw, char numOfBytes, uint64_t address, cache_stats_t* p_stats); 37 | }; 38 | 39 | struct mallocStats 40 | { 41 | uint32_t bbid; 42 | uint32_t size; 43 | uint32_t misses; 44 | }; 45 | 46 | class SimpleCacheBackend : public contech::Backend 47 | { 48 | std::map contextCacheState; 49 | std::map basicBlockMisses; 50 | std::map allocBlocks; 51 | cache_stats_t* p_stats; 52 | bool printMissLines; 53 | 54 | public: 55 | virtual void resetBackend(); 56 | virtual void updateBackend(contech::Task*); 57 | virtual void completeBackend(FILE*, contech::TaskGraphInfo*); 58 | 59 | SimpleCacheBackend(uint64_t c, uint64_t s, int printMissLoc); 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /backend/Statistics/.gitignore: -------------------------------------------------------------------------------- 1 | stats 2 | -------------------------------------------------------------------------------- /backend/Statistics/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -std=c++11 -O3 3 | OBJECTS= stats.o 4 | INCLUDES= 5 | LIBS= -L../../common/taskLib -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | 7 | all: taskLib stats 8 | 9 | taskLib: 10 | make -C ../../common/taskLib 11 | 12 | %.o : %.cpp 13 | $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< 14 | stats: $(OBJECTS) 15 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) 16 | 17 | clean: 18 | rm -f *.o 19 | rm -f stats 20 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/IFrontEnd.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Interface class for an x86 instruction front-end 5 | class IFrontEnd 6 | { 7 | public: 8 | 9 | // Represents an x86 instruction, along with memory addresses accessed 10 | struct Instruction 11 | { 12 | uint32_t addr; 13 | unsigned int length; 14 | unsigned int bytes[15]; 15 | unsigned int reads; 16 | unsigned int writes; 17 | char opcode[16]; 18 | uint32_t readAddr[2]; 19 | uint32_t writeAddr[2]; 20 | }; 21 | 22 | // Cpu Id of the frontend 23 | virtual unsigned int getCpuId() = 0; 24 | // Gets the next instruction in the trace. Upon reaching the end of the trace, returns false and does not provide a valid instruction. 25 | virtual bool getNextInstruction(Instruction& inst) = 0; 26 | // Returns a string representation of the frontend's position in the trace, useful for debugging 27 | virtual std::string getPositionString() = 0; 28 | virtual void TaskGraphRegisterCallback(void (*param)(long)) = 0; 29 | }; 30 | 31 | // Implemented in libTaskGraphFrontend 32 | IFrontEnd* createTaskGraphFrontEnd(std::string basename, unsigned int cpuId); 33 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = libTaskGraphFrontEnd.a 2 | CXX=g++ 3 | CXXFLAGS= -g -std=c++11 -O3 4 | OBJECTS= TaskGraphFrontEnd.o markedInstruction.o markedBlock.o markedCodeContainer.o 5 | INCLUDES= 6 | LIBS= -L../../common/taskLib/ -lTask -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 7 | EXTERNALS= 8 | 9 | all: $(PROJECT) 10 | 11 | install: all 12 | cp IFrontEnd.hpp /net/tinker/local/include/ 13 | cp libTaskGraphFrontEnd.a /net/tinker/local/lib/ 14 | 15 | markedCodeContainerTest: all markedCodeContainer_test.o 16 | $(CXX) $(CXXFLAGS) markedCodeContainer_test.o markedInstruction.o markedBlock.o markedCodeContainer.o -o markedCodeContainer_test 17 | ./markedCodeContainer_test 18 | 19 | TaskGraphFrontEndTest: all markedCodeContainer_test.o TaskGraphFrontEnd_test.o 20 | # $(CXX) TaskGraphFrontEnd_test.o $(CXXFLAGS) $(LIBS) -L. -lTaskGraphFrontEnd -o TaskGraphFrontEnd_test 21 | g++ TaskGraphFrontEnd_test.o ../../common/taskLib/Task.o ../../common/taskLib/ct_file.o -g -std=c++11 -O3 -L../../common/taskLib/ -lTask -lz -L. -lTaskGraphFrontEnd -o TaskGraphFrontEnd_test 22 | ./TaskGraphFrontEnd_test 23 | 24 | test: markedCodeContainerTest TaskGraphFrontEndTest 25 | 26 | %.o : %.cpp 27 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 28 | $(PROJECT): $(OBJECTS) 29 | ar rc $(PROJECT) $(OBJECTS) 30 | 31 | clean: 32 | rm -f *.o 33 | rm -f $(PROJECT) 34 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/TaskGraphFrontEnd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TASKGRAPH_FRONTEND_H 2 | #define TASKGRAPH_FRONTEND_H 3 | 4 | #include "../../common/taskLib/TaskGraph.hpp" 5 | #include "markedCodeContainer.hpp" 6 | #include 7 | #include 8 | #include 9 | #include "IFrontEnd.hpp" 10 | 11 | #define DEBUG true 12 | 13 | class TaskGraphFrontEnd : public IFrontEnd 14 | { 15 | public: 16 | TaskGraphFrontEnd(std::string basename, unsigned int cpuId); 17 | 18 | virtual unsigned int getCpuId(); 19 | virtual bool getNextInstruction(IFrontEnd::Instruction& inst); 20 | virtual string getPositionString(); 21 | virtual void TaskGraphRegisterCallback(void (*param)(long)); 22 | 23 | private: 24 | 25 | unsigned int cpuId; 26 | bool isMyTask(contech::Task* task); 27 | void (*callback)(long) = NULL; 28 | void convert(const markedInstruction& m, IFrontEnd::Instruction& dst); 29 | 30 | // Maintain position within the task graph 31 | FILE* taskGraphFile; 32 | contech::TaskGraph* tg; 33 | contech::Task* currentTask; 34 | contech::Task::basicBlockActionCollection blocksInTask; 35 | contech::Task::basicBlockActionCollection::iterator currentBlockId; 36 | contech::Task::memOpCollection memOpsInBlock; 37 | contech::Task::memOpCollection::iterator currentMemOp; 38 | 39 | // Maintain position within the marked code container 40 | markedCodeContainer* markedCode; 41 | markedBlock* currentBlock; 42 | markedBlock::iterator currentInstruction; 43 | 44 | }; 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/TaskGraphFrontEnd_test.cpp: -------------------------------------------------------------------------------- 1 | #include "IFrontEnd.hpp" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Tests 8 | void test(); 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | test(); 13 | 14 | return 0; 15 | } 16 | 17 | 18 | void test() 19 | { 20 | std::map programMap; 21 | 22 | for (unsigned int coreId = 0; coreId < 1; coreId++) 23 | { 24 | std::cout << "Constructing frontend object for core " << coreId << std::endl; 25 | IFrontEnd* frontend = createTaskGraphFrontEnd("/net/tinker/dcook31/contech/middle/output/helloWorld",coreId); 26 | IFrontEnd::Instruction inst; 27 | 28 | 29 | 30 | while (frontend->getNextInstruction(inst)) 31 | { 32 | programMap[string(inst.opcode)] = programMap[string(inst.opcode)] + 1; 33 | printf("Instruction: %s Count: %d\n",inst.opcode,programMap[string(inst.opcode)]); 34 | 35 | /* 36 | cout << frontend.getPositionString() << endl; 37 | 38 | cout << inst.toString(); 39 | if (inst.reads == 1) 40 | { 41 | cout << "R [" << hex << inst.readAddr[0] << "]"; 42 | } 43 | else if (inst.writes == 1) 44 | { 45 | cout << "W [" << hex << inst.writeAddr[0] << "]"; 46 | } 47 | cout << endl; 48 | */ 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "markedBlock.hpp" 2 | 3 | markedBlock::iterator markedBlock::begin() { return instructions.begin(); } 4 | markedBlock::iterator markedBlock::end() { return instructions.end(); } 5 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedBlock.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MARKED_BLOCK_H 2 | #define MARKED_BLOCK_H 3 | 4 | #include "markedInstruction.hpp" 5 | #include 6 | 7 | class markedBlock 8 | { 9 | // markedCodeContainer basically does all the construction of this class by inserting instructions 10 | friend class markedCodeContainer; 11 | 12 | public: 13 | typedef std::vector::iterator iterator; 14 | 15 | iterator begin(); 16 | iterator end(); 17 | private: 18 | 19 | std::vector instructions; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedCodeContainer.cpp: -------------------------------------------------------------------------------- 1 | #include "markedCodeContainer.hpp" 2 | 3 | markedBlock* markedCodeContainer::getBlock(unsigned int id) { return blocks[id]; }; 4 | 5 | markedCodeContainer* markedCodeContainer::fromFile(std::string inFile) 6 | { 7 | markedCodeContainer* container = new markedCodeContainer(); 8 | 9 | // Open the file 10 | std::ifstream in(inFile); 11 | 12 | // Format: 13 | // bbId 14 | // instruction 15 | // ... 16 | // instruction 17 | // 18 | // bbId 19 | // instruction 20 | // ... 21 | // instruction 22 | 23 | std::string line; 24 | while (std::getline(in, line)) 25 | { 26 | std::istringstream stream(line); 27 | uint bbId; 28 | stream >> bbId; 29 | 30 | std::getline(in, line); 31 | markedBlock* b = new markedBlock(); 32 | while (line != "") 33 | { 34 | b->instructions.push_back(markedInstruction::fromString(line)); 35 | std::getline(in, line); 36 | } 37 | // for (auto i = b->begin(), e = b->end(); i != e; ++i) 38 | // { 39 | // std::cout << (*i).toString() << std::endl; 40 | // } 41 | container->blocks[bbId] = b; 42 | } 43 | 44 | in.close(); 45 | return container; 46 | } 47 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedCodeContainer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MARKED_CODE_CONTAINER_H 2 | #define MARKED_CODE_CONTAINER_H 3 | 4 | #include "markedInstruction.hpp" 5 | #include "markedBlock.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class markedCodeContainer 12 | { 13 | public: 14 | markedBlock* getBlock(unsigned int id); 15 | static markedCodeContainer* fromFile(std::string in); 16 | 17 | private: 18 | std::map blocks; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedCodeContainer_test.cpp: -------------------------------------------------------------------------------- 1 | #include "markedCodeContainer.hpp" 2 | 3 | using namespace std; 4 | // Tests 5 | void test(); 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | test(); 10 | 11 | return 0; 12 | } 13 | 14 | 15 | void test() 16 | { 17 | markedCodeContainer* container = markedCodeContainer::fromFile("/net/tinker/ehein6/contech/middle/output/barr.mo"); 18 | 19 | uint bbId = 0; 20 | for (uint bbId = 0; bbId < 87; bbId++) 21 | { 22 | cout << endl << bbId << endl; 23 | markedBlock* bb = container->getBlock(bbId); 24 | if (bb == NULL) continue; 25 | 26 | for (markedInstruction inst : *bb) 27 | { 28 | cout << inst.toString() << endl; 29 | } 30 | 31 | // TODO Capture output and diff against input file 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedInstruction.cpp: -------------------------------------------------------------------------------- 1 | #include "markedInstruction.hpp" 2 | #include 3 | 4 | markedInstruction markedInstruction::fromString(std::string s) 5 | { 6 | markedInstruction inst; 7 | // Format of line: 8 | // reads writes addr char[] byte byte byte byte ... byte 9 | std::istringstream stream(s); 10 | stream >> std::hex >> inst.reads >> std::hex >> inst.writes >> std::hex >> inst.addr; 11 | stream.get(); 12 | stream.get(inst.opcode,16,' '); 13 | for(int i = 0; i < 16; i++){ 14 | inst.opcode[i] = tolower(inst.opcode[i]); 15 | } 16 | 17 | for (inst.length = 0; stream >> std::hex >> inst.bytes[inst.length]; inst.length++); 18 | 19 | return inst; 20 | } 21 | 22 | std::string markedInstruction::toString() 23 | { 24 | std::ostringstream out; 25 | out << reads << " " << writes << " " << length << " " << std::hex << addr << " "; 26 | for (uint i = 0; i < length; i++) 27 | { 28 | out << std::hex << std::setfill('0') << std::setw(2) << bytes[i] << " "; 29 | } 30 | return out.str(); 31 | } 32 | -------------------------------------------------------------------------------- /backend/TaskGraphFrontEnd/markedInstruction.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MARKED_INSTRUCTION_H 2 | #define MARKED_INSTRUCTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class markedInstruction 10 | { 11 | public: 12 | uint32_t addr; 13 | uint length; 14 | uint bytes[15]; 15 | uint reads; 16 | uint writes; 17 | char opcode[16]; 18 | 19 | static markedInstruction fromString(std::string s); 20 | std::string toString(); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /backend/TaskGraphVisualizer/.gitignore: -------------------------------------------------------------------------------- 1 | taskViz 2 | -------------------------------------------------------------------------------- /backend/TaskGraphVisualizer/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS= -g -std=c++11 -O3 3 | OBJECTS= taskViz.o 4 | INCLUDES= -I. 5 | LIBS= -L/net/tinker/local/lib64 -L/net/tinker/local/lib -lgvc -lcgraph -L../../common/taskLib/ -lTask -L../CommTracker -lCommTracker -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | EXTERNALS= 7 | 8 | all: taskLib taskViz 9 | 10 | taskLib: 11 | make -C ../../common/taskLib 12 | 13 | %.o : %.cpp 14 | $(CXX) $< $(CXXFLAGS) $(INCLUDES) -c -o $@ 15 | taskViz: $(OBJECTS) 16 | $(CXX) $^ $(CXXFLAGS) $(LIBS) -o $@ $(EXTERNALS) 17 | 18 | clean: 19 | rm -f *.o 20 | rm -f taskViz 21 | -------------------------------------------------------------------------------- /backend/TaskGraphVisualizer/output/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.svg 3 | 4 | -------------------------------------------------------------------------------- /backend/TaskGraphVisualizer/output/about.txt: -------------------------------------------------------------------------------- 1 | This folder is for holding task graph image files that are created by various scripts. 2 | -------------------------------------------------------------------------------- /common/eventLib/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = libct_event.a 2 | OBJECTS = ct_event.o 3 | CFLAGS = -O2 -g --std=c++11 4 | HEADERS = ct_event.h ct_event_st.h 5 | 6 | all: $(PROJECT) 7 | 8 | .cpp.o: 9 | g++ -c $(CFLAGS) $< 10 | 11 | $(PROJECT): $(OBJECTS) 12 | ar rc $(PROJECT) $(OBJECTS) 13 | 14 | clean: 15 | rm $(PROJECT) $(OBJECTS) 16 | -------------------------------------------------------------------------------- /common/eventLib/ct_event_st.h: -------------------------------------------------------------------------------- 1 | #ifndef CT_EVENT_ST_H 2 | #define CT_EVENT_ST_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define CONTECH_EVENT_VERSION 9 9 | 10 | typedef uint64_t ct_tsc_t; 11 | typedef uint64_t ct_addr_t; 12 | 13 | typedef struct _ct_memory_op { 14 | union { 15 | struct { 16 | // NB. Addr must come first so that the storing to data32[0] is completely stored into 17 | // the address field. 18 | uint64_t addr : 48; 19 | uint64_t resrv : 2; 20 | uint64_t rank : 8; 21 | uint64_t is_write : 1; 22 | uint64_t pow_size : 3; // the size of the op is 2^pow_size 23 | }; 24 | uint64_t data; 25 | uint32_t data32[2]; 26 | }; 27 | } ct_memory_op, *pct_memory_op; 28 | 29 | // Event IDs used primarily in serialize / deserialize 30 | enum _ct_event_id { ct_event_basic_block = 0, 31 | ct_event_basic_block_info = 128, 32 | ct_event_memory, 33 | ct_event_sync, 34 | ct_event_barrier, 35 | ct_event_task_create, 36 | ct_event_task_join, 37 | ct_event_buffer, // INTERNAL USE 38 | ct_event_bulk_memory_op, 39 | ct_event_version, // INTERNAL USE 40 | ct_event_delay, 41 | ct_event_rank, 42 | ct_event_mpi_transfer, 43 | ct_event_mpi_allone, 44 | ct_event_mpi_wait, 45 | ct_event_roi, 46 | ct_event_gv_info, 47 | ct_event_loop_enter, 48 | ct_event_loop_short, 49 | ct_event_loop_exit, 50 | ct_event_path_info, 51 | ct_event_unknown}; 52 | typedef enum _ct_event_id ct_event_id; 53 | 54 | enum _ct_sync_type { 55 | ct_sync_release = 0, 56 | ct_sync_acquire = 1, 57 | ct_cond_wait, 58 | ct_cond_sig, 59 | ct_sync_atomic, 60 | ct_task_depend, 61 | ct_sync_unknown}; 62 | typedef enum _ct_sync_type ct_sync_type; 63 | 64 | #define BBI_FLAG_CONTAIN_CALL 0x1 65 | #define BBI_FLAG_MEM_DUP 0x2 66 | #define BBI_FLAG_MEM_GV 0x4 67 | #define BBI_FLAG_MEM_LOOP 0x8 68 | #define BBI_FLAG_MEM_PRESV 0x10 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /common/runtime/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = libct_runtime.a 2 | OBJECTS = ct_runtime.o 3 | CFLAGS = -O3 -g 4 | HEADERS = ct_runtime.h 5 | BITCODE = ct_runtime.bc ct_main.bc ct_mpi.bc ct_nompi.bc 6 | 7 | .SUFFIXES: 8 | .SUFFIXES: .bc .c 9 | 10 | all: $(BITCODE) 11 | 12 | .c.bc: $(HEADERS) 13 | clang -emit-llvm -I. -c $(CFLAGS) -DCT_MAIN $< 14 | 15 | clean: 16 | rm $(BITCODE) 17 | -------------------------------------------------------------------------------- /common/runtime/ct_mpi.c: -------------------------------------------------------------------------------- 1 | #include "ct_runtime.h" 2 | #include 3 | #include 4 | 5 | #ifdef CT_MPI_NOT_PRESENT 6 | 7 | #else 8 | int __ctIsMPIPresent() 9 | { 10 | return 1; 11 | } 12 | 13 | int __ctGetMPIRank() 14 | { 15 | int rank = 0; 16 | int flag = 0; 17 | MPI_Initialized(&flag); 18 | while (flag == 0) 19 | { 20 | sched_yield(); 21 | MPI_Initialized(&flag); 22 | } 23 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 24 | return rank; 25 | } 26 | 27 | int __ctGetSizeofMPIDatatype(int datatype) 28 | { 29 | int size = 0; 30 | MPI_Type_size(datatype, &size); 31 | return size; 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /common/runtime/ct_nompi.c: -------------------------------------------------------------------------------- 1 | #include "ct_runtime.h" 2 | 3 | int __ctIsMPIPresent() 4 | { 5 | return 0; 6 | } 7 | 8 | int __ctGetMPIRank() 9 | { 10 | return 0; 11 | } 12 | 13 | int __ctGetSizeofMPIDatatype(int datatype) 14 | { 15 | return 0; 16 | } -------------------------------------------------------------------------------- /common/runtime/mpi.h: -------------------------------------------------------------------------------- 1 | #ifndef MPI_H 2 | #define MPI_H 3 | #define CT_MPI_NOT_PRESENT 4 | #endif 5 | 6 | -------------------------------------------------------------------------------- /common/runtime/rdtsc.h: -------------------------------------------------------------------------------- 1 | #ifndef __RDTSC_H_DEFINED__ 2 | #define __RDTSC_H_DEFINED__ 3 | #include 4 | 5 | #if defined(__i386__) 6 | 7 | static __inline__ uint64_t rdtsc(void) 8 | { 9 | uint64_t x; 10 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); 11 | return x; 12 | } 13 | #elif defined(__x86_64__) 14 | 15 | static __inline__ uint64_t rdtsc(void) 16 | { 17 | uint32_t hi, lo; 18 | __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 19 | return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); 20 | } 21 | 22 | #elif defined(__powerpc__) 23 | 24 | static __inline__ uint64_t rdtsc(void) 25 | { 26 | uint64_t result=0; 27 | uint32_t upper, lower,tmp; 28 | __asm__ volatile( 29 | "0: \n" 30 | "\tmftbu %0 \n" 31 | "\tmftb %1 \n" 32 | "\tmftbu %2 \n" 33 | "\tcmpw %2,%0 \n" 34 | "\tbne 0b \n" 35 | : "=r"(upper),"=r"(lower),"=r"(tmp) 36 | ); 37 | result = upper; 38 | result = result<<32; 39 | result = result|lower; 40 | 41 | return(result); 42 | } 43 | 44 | #elif defined (__arm__) 45 | 46 | static __inline__ uint64_t rdtsc(void) 47 | { 48 | unsigned int x = 0; 49 | // May not be enabled by kernel 50 | // Replace with C - clock() or C++ chrono? 51 | __asm__ volatile ("MRC p15, 0, %0, c9, c13, 0\n\t": "=r" (x)::); 52 | return x; 53 | } 54 | 55 | #else 56 | 57 | #error "No tick counter is available!" 58 | 59 | #endif 60 | 61 | 62 | /* $RCSfile: $ $Author: kazutomo $ 63 | * $Revision: 1.6 $ $Date: 2005/04/13 18:49:58 $ 64 | */ 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /common/taskLib/.gitignore: -------------------------------------------------------------------------------- 1 | libTask.so 2 | -------------------------------------------------------------------------------- /common/taskLib/Action.cpp: -------------------------------------------------------------------------------- 1 | #include "Action.hpp" 2 | using namespace contech; 3 | 4 | MemoryAction::MemoryAction() {} 5 | MemoryAction::MemoryAction(Action a) : data(a.data) {} 6 | BasicBlockAction::BasicBlockAction() {} 7 | BasicBlockAction::BasicBlockAction(Action a) : data(a.data) {} 8 | 9 | Action::Action() {} 10 | Action::Action(BasicBlockAction a) : data(a.data) {}; 11 | Action::Action(MemoryAction a) : data(a.data) {}; 12 | action_type Action::getType() const { return (action_type)type; } 13 | bool Action::isMemOp() const { return type == action_type_mem_read || type == action_type_mem_write; } 14 | bool Action::isMemoryAction() const { return type != action_type_basicBlock; } 15 | bool Action::isBasicBlockAction() const { return type == action_type_basicBlock; } 16 | bool Action::operator==(const Action& rhs) const { return data == rhs.data; } 17 | bool Action::operator!=(const Action& rhs) const { return data != rhs.data; } 18 | bool operator< (const Action& lhs, const Action& rhs){ return lhs.data < rhs.data; } 19 | bool operator< (const MemoryAction& lhs, const MemoryAction& rhs){ return lhs.data < rhs.data; } 20 | bool operator< (const BasicBlockAction& lhs, const BasicBlockAction& rhs){ return lhs.data < rhs.data; } 21 | 22 | std::string Action::toString() const 23 | { 24 | std::ostringstream out; 25 | out << std::showbase; 26 | switch (type) 27 | { 28 | case action_type_basicBlock: 29 | { 30 | BasicBlockAction bb = *this; 31 | out << " BB#" << bb.basic_block_id; 32 | break; 33 | } 34 | case action_type_mem_write: 35 | { 36 | MemoryAction mem = *this; 37 | out << " ST " << std::hex << mem.addr; 38 | break; 39 | } 40 | case action_type_mem_read: 41 | { 42 | MemoryAction mem = *this; 43 | out << " LD " << std::hex << mem.addr; 44 | break; 45 | } 46 | case action_type_malloc: 47 | { 48 | MemoryAction mem = *this; 49 | out << " malloc " << std::hex << mem.addr; 50 | break; 51 | } 52 | case action_type_size: 53 | { 54 | MemoryAction mem = *this; 55 | out << " of size " << mem.addr; 56 | break; 57 | } 58 | case action_type_free: 59 | { 60 | MemoryAction mem = *this; 61 | out << " free " << std::hex << mem.addr; 62 | break; 63 | } 64 | 65 | case action_type_memcpy: 66 | { 67 | MemoryAction mem = *this; 68 | out << " memcpy addr " << std::hex << mem.addr; 69 | break; 70 | } 71 | 72 | default: 73 | { 74 | out << " UNKNOWN: " << data; 75 | } 76 | } 77 | return out.str(); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /common/taskLib/Action.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CT_ACTION_H 2 | #define CT_ACTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | namespace contech { 8 | 9 | // The action class encodes all the different "actions" that a task can take. 10 | // It is a 64 bit value. The first three bits determine what type of action it is. 11 | struct Action; // forward reference 12 | 13 | // Enum that decodes the first three bits of an action into an action type 14 | enum action_type 15 | { 16 | action_type_null = 0, 17 | action_type_mem_read = 1, 18 | action_type_mem_write = 2, 19 | action_type_free = 3, 20 | action_type_malloc = 4, 21 | action_type_size = 5, 22 | action_type_basicBlock = 6, 23 | action_type_memcpy = 7 24 | // If you add more action types, recheck the methods of Action to ensure no assumptions are broken 25 | }; 26 | 27 | // Next, we define the layout for each type of action. It is critical that each one reserves three bits for the action type. 28 | 29 | // Load/store or allocation 30 | struct MemoryAction 31 | { 32 | union { 33 | struct { 34 | uint64_t addr : 48; 35 | uint64_t resrv : 2; 36 | uint64_t rank : 8; 37 | uint64_t pow_size : 3; // the size of the read or write is 2^pow_size 38 | uint64_t type : 3; 39 | }; 40 | uint64_t data; 41 | }; 42 | MemoryAction(); 43 | MemoryAction(Action a); 44 | MemoryAction(uint64_t a, uint64_t ps, action_type at) {data = 0; addr = a; pow_size = ps; type = at;} 45 | }; 46 | bool operator< (const MemoryAction& lhs, const MemoryAction& rhs); 47 | 48 | 49 | // Basic block 50 | struct BasicBlockAction 51 | { 52 | union { 53 | struct { 54 | uint64_t basic_block_id : 32; 55 | uint64_t reserv : 29; 56 | uint64_t type : 3; 57 | }; 58 | uint64_t data; 59 | }; 60 | BasicBlockAction(); 61 | BasicBlockAction(Action a); 62 | }; 63 | bool operator< (const BasicBlockAction& lhs, const BasicBlockAction& rhs); 64 | 65 | // Finally, overlay all the different action structs into a single 64 bit layout 66 | struct Action 67 | { 68 | union { 69 | struct { 70 | uint64_t junk : 61; 71 | uint64_t type : 3; 72 | }; 73 | // Raw bits 74 | uint64_t data; 75 | }; 76 | 77 | Action(); 78 | Action(BasicBlockAction a); 79 | Action(MemoryAction a); 80 | action_type getType() const; 81 | bool isMemOp() const; 82 | bool isMemoryAction() const; 83 | bool isBasicBlockAction() const; 84 | bool operator==(const Action& rhs) const; 85 | bool operator!=(const Action& rhs) const; 86 | std::string toString() const; 87 | }; 88 | 89 | bool operator< (const Action& lhs, const Action& rhs); 90 | inline static std::ostream& operator<<(std::ostream& os, const Action& i) { os << i.toString(); return os; } 91 | 92 | } // end namespace contech 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /common/taskLib/Backend.cpp: -------------------------------------------------------------------------------- 1 | #include "Backend.hpp" 2 | #include "TaskGraph.hpp" 3 | 4 | using namespace contech; 5 | 6 | void Backend::initBackend(TaskGraphInfo*) {} 7 | 8 | SimpleBackendWrapper::SimpleBackendWrapper(char* f, Backend* b) : backend(b) 9 | { 10 | tg = TaskGraph::initFromFile(f); 11 | assert(tg != NULL); 12 | } 13 | 14 | void SimpleBackendWrapper::runBackend() 15 | { 16 | Task* t = NULL; 17 | 18 | while ((t = tg->getNextTask()) != NULL) 19 | { 20 | backend->updateBackend(t); 21 | delete t; 22 | } 23 | } 24 | 25 | void SimpleBackendWrapper::initBackend() 26 | { 27 | backend->initBackend(tg->getTaskGraphInfo()); 28 | } 29 | 30 | void SimpleBackendWrapper::completeRun(FILE* f) 31 | { 32 | backend->completeBackend(f, tg->getTaskGraphInfo()); 33 | fflush(f); 34 | } 35 | 36 | SimpleBackendWrapper::~SimpleBackendWrapper() 37 | { 38 | delete tg; 39 | } -------------------------------------------------------------------------------- /common/taskLib/Backend.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONTECH_BACKEND_HPP 2 | #define CONTECH_BACKEND_HPP 3 | 4 | #include "TaskGraph.hpp" 5 | 6 | namespace contech 7 | { 8 | 9 | class Backend 10 | { 11 | public: 12 | virtual void initBackend(contech::TaskGraphInfo*); 13 | virtual void resetBackend() = 0; 14 | virtual void updateBackend(contech::Task*) = 0; 15 | virtual void completeBackend(FILE*, contech::TaskGraphInfo*) = 0; 16 | }; 17 | 18 | class SimpleBackendWrapper 19 | { 20 | private: 21 | TaskGraph* tg; 22 | Backend* backend; 23 | 24 | public: 25 | SimpleBackendWrapper(char*, contech::Backend*); 26 | ~SimpleBackendWrapper(); 27 | void runBackend(); 28 | void initBackend(); 29 | void completeRun(FILE*); 30 | }; 31 | 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /common/taskLib/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = libTask.so 2 | OBJECTS = TaskGraph.o TaskGraphInfo.o Task.o Action.o ct_file.o Backend.o 3 | CC = gcc 4 | CFLAGS = -O3 -g -Wall -pthread -fPIC 5 | CXX = g++ 6 | CXXFLAGS = -std=c++11 -O3 -g -Wall -pthread -fPIC 7 | HEADERS = Task.h 8 | 9 | all: $(PROJECT) 10 | 11 | $(PROJECT): $(OBJECTS) 12 | #ar rc $(PROJECT) $(OBJECTS) 13 | $(CXX) $(CXXFLAGS) -shared -o $(PROJECT) -lz $(OBJECTS) 14 | 15 | objects: $(OBJECTS) 16 | 17 | 18 | # ct_file is compiled separately for c and c++ usage 19 | #ct_file.o: 20 | # g++ -c $(CXXFLAGS) ct_file.c -o ct_file.o 21 | 22 | 23 | .PHONY: test 24 | 25 | .PHONY: clean 26 | clean: 27 | rm -f $(PROJECT) $(OBJECTS) 28 | rm -f Task_test 29 | -------------------------------------------------------------------------------- /common/taskLib/TaskGraph.cpp: -------------------------------------------------------------------------------- 1 | #include "TaskGraph.hpp" 2 | 3 | using namespace contech; 4 | 5 | // 6 | // Cannot call constructor directly, but wrap with "factory" 7 | // 8 | TaskGraph* TaskGraph::initFromFile(char* fname) 9 | { 10 | FILE* f = fopen(fname, "rb"); 11 | 12 | if (f == NULL) { return NULL;} 13 | else {return new TaskGraph(f);} 14 | } 15 | 16 | TaskGraph* TaskGraph::initFromFile(const char* fname) 17 | { 18 | FILE* f = fopen(fname, "rb"); 19 | 20 | if (f == NULL) { return NULL;} 21 | else {return new TaskGraph(f);} 22 | } 23 | 24 | TaskGraph* TaskGraph::initFromFile(FILE* f) 25 | { 26 | if (f == NULL) { return NULL;} 27 | else {return new TaskGraph(f);} 28 | } 29 | 30 | // 31 | // Construct a task graph from the file 32 | // 33 | TaskGraph::TaskGraph(FILE* f) 34 | { 35 | uint version = 0; 36 | uint64 taskIndexOffset = 0; 37 | inputFile = f; 38 | 39 | // This is to ensure the file is at the start 40 | fseek(f, 0, SEEK_SET); 41 | 42 | // First is the version number 43 | if (sizeof(uint32_t) != ct_read(&version, sizeof(uint32_t), f)) 44 | { 45 | fprintf(stderr, "TASK GRAPH - Error reading from input file\n"); 46 | return; 47 | } 48 | 49 | if (version != TASK_GRAPH_VERSION) 50 | { 51 | fprintf(stderr, "TASK GRAPH - Warning version number is %u, expected %u\n", version, TASK_GRAPH_VERSION); 52 | } 53 | 54 | // Next is the location of the taskIndex in the file 55 | ct_read(&taskIndexOffset, sizeof(uint64), f); 56 | ct_read(&ROIStart, sizeof(TaskId), f); 57 | ct_read(&ROIEnd, sizeof(TaskId), f); 58 | 59 | // Then comes the taskGraphInfo structure 60 | tgi = readTaskGraphInfo(); 61 | 62 | // Now skip to the index 63 | initTaskIndex(taskIndexOffset); 64 | } 65 | 66 | TaskGraph::~TaskGraph() 67 | { 68 | taskOrder.clear(); 69 | delete tgi; 70 | } 71 | 72 | // 73 | // Get next task from the order 74 | // 75 | Task* TaskGraph::getNextTask() 76 | { 77 | if (nextTask == taskOrder.end()) return NULL; 78 | 79 | //if ((e = ct_lock(inputFile))) return NULL; 80 | 81 | fseek(inputFile, *nextTask, SEEK_SET); 82 | ++nextTask; 83 | 84 | return Task::readContechTaskUnlock(inputFile); 85 | } 86 | 87 | void TaskGraph::resetTaskOrder() 88 | { 89 | nextTask = taskOrder.begin(); 90 | } 91 | 92 | // 93 | // Sets the specified TaskId as the current task 94 | // getNextTask will retrieve the next task starting with TaskId 95 | // 96 | void TaskGraph::setTaskOrderCurrent(TaskId tid) 97 | { 98 | uint64_t tidPos = taskIdx[tid]; 99 | while (nextTask != taskOrder.end() && 100 | *nextTask != tidPos) {++nextTask;} 101 | } 102 | 103 | // 104 | // Request tasks in order until ID is found 105 | // 106 | Task* TaskGraph::getTaskById(TaskId id) 107 | { 108 | auto it = taskIdx.find(id); 109 | 110 | if (it == taskIdx.end()) return NULL; 111 | 112 | //if (ct_lock(inputFile)) return NULL; 113 | fseek(inputFile, it->second, SEEK_SET); 114 | 115 | return Task::readContechTaskUnlock(inputFile); 116 | } 117 | 118 | Task* TaskGraph::readContechTask() 119 | { 120 | if (inputFile == NULL) return NULL; 121 | return getNextTask(); 122 | } 123 | 124 | Task* TaskGraph::getContechTask(TaskId tid) 125 | { 126 | if (inputFile == NULL) return NULL; 127 | return getTaskById(tid); 128 | } 129 | 130 | TaskGraphInfo* TaskGraph::getTaskGraphInfo() 131 | { 132 | return tgi; 133 | } 134 | 135 | void TaskGraph::initTaskIndex(uint64 off) 136 | { 137 | if (0 != fseek(inputFile, off, SEEK_SET)) 138 | { 139 | fprintf(stderr, "Failed to seek to specified offset for Task Graph Index - %lu\n", off); 140 | return; 141 | } 142 | //printf("At %lld, ready to read index\n", off); 143 | 144 | uint64 taskCount; 145 | ct_read(&taskCount, sizeof(uint64), inputFile); 146 | //printf("Tasks in index - %llu\n", taskCount); 147 | 148 | set uniqContexts; 149 | 150 | for (uint i = 0; i < taskCount; i++) 151 | { 152 | TaskId tid; 153 | uint64 pos; 154 | 155 | ct_read(&tid, sizeof(TaskId), inputFile); 156 | ct_read(&pos, sizeof(uint64), inputFile); 157 | 158 | //printf("%s at %llu\n", tid.toString().c_str(), pos); 159 | 160 | // We expect that the index comes after every task in the file 161 | assert(pos < off); 162 | // Every tid should only exist once in the index 163 | assert(taskIdx.find(tid) == taskIdx.end()); 164 | taskIdx[tid] = pos; 165 | taskOrder.push_back(pos); 166 | uniqContexts.insert(tid.getContextId()); 167 | } 168 | nextTask = taskOrder.begin(); 169 | numOfContexts = uniqContexts.size(); 170 | } 171 | 172 | TaskGraphInfo* TaskGraph::readTaskGraphInfo() 173 | { 174 | // Task Graph Info follows the version number + task index offset 175 | // assert(inputFile is at offset 4 + 8) 176 | 177 | TaskGraphInfo* tTgi = new TaskGraphInfo(); 178 | tTgi->initTaskGraphInfo(inputFile); 179 | 180 | return tTgi; 181 | } 182 | 183 | unsigned int TaskGraph::getNumberOfTasks() 184 | { 185 | return taskOrder.size(); 186 | } 187 | 188 | unsigned int TaskGraph::getNumberOfContexts() 189 | { 190 | return numOfContexts; 191 | } 192 | 193 | TaskId TaskGraph::getROIStart() 194 | { 195 | return ROIStart; 196 | } 197 | 198 | TaskId TaskGraph::getROIEnd() 199 | { 200 | return ROIEnd; 201 | } 202 | -------------------------------------------------------------------------------- /common/taskLib/TaskGraph.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TASK_GRAPH_HPP 2 | #define TASK_GRAPH_HPP 3 | 4 | #include "Task.hpp" 5 | #include "TaskGraphInfo.hpp" 6 | #include "TaskId.hpp" 7 | #include "Action.hpp" 8 | #include "ct_file.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define TASK_GRAPH_VERSION 4315 22 | 23 | using namespace std; 24 | namespace contech { 25 | 26 | class TaskGraph 27 | { 28 | private: 29 | FILE* inputFile; 30 | TaskGraphInfo* tgi; 31 | 32 | // Use an index to find each task in the graph 33 | // TaskId -> position in file 34 | map taskIdx; 35 | 36 | // Store the positions of each task 37 | vector taskOrder; 38 | vector::iterator nextTask; 39 | 40 | TaskId ROIStart; 41 | TaskId ROIEnd; 42 | 43 | unsigned int numOfContexts; 44 | 45 | // Privately, attempt to read a task graph info struct 46 | TaskGraphInfo* readTaskGraphInfo(); 47 | void initTaskIndex(uint64); 48 | 49 | TaskGraph(FILE*); 50 | 51 | public: 52 | static TaskGraph* initFromFile(char*); 53 | static TaskGraph* initFromFile(const char*); 54 | static TaskGraph* initFromFile(FILE*); 55 | 56 | Task* getNextTask(); 57 | Task* getTaskById(TaskId id); 58 | void setTaskOrderCurrent(TaskId tid); 59 | void resetTaskOrder(); 60 | 61 | unsigned int getNumberOfTasks(); 62 | unsigned int getNumberOfContexts(); 63 | 64 | // These calls are deprecated and will be removed soon... 65 | Task* readContechTask(); 66 | Task* getContechTask(TaskId); 67 | 68 | TaskId getROIStart(); 69 | TaskId getROIEnd(); 70 | 71 | TaskGraphInfo* getTaskGraphInfo(); 72 | ~TaskGraph(); 73 | }; 74 | 75 | } 76 | 77 | #endif -------------------------------------------------------------------------------- /common/taskLib/TaskGraphInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "TaskGraphInfo.hpp" 2 | 3 | using namespace contech; 4 | 5 | void TaskGraphInfo::initTaskGraphInfo(FILE* in) 6 | { 7 | int numBasicBlock = 0; 8 | 9 | ct_read(&numBasicBlock, sizeof(int), in); 10 | for (int i = 0; i < numBasicBlock; i++) 11 | { 12 | uint strLen; 13 | uint bbid = 0, flags = 0; 14 | uint lineNumber, numOfMemOps, numOps, critPathLen; 15 | char* f; 16 | string function, file, callsFunction; 17 | 18 | ct_read(&bbid, sizeof(uint), in); 19 | ct_read(&flags, sizeof(uint), in); 20 | ct_read(&lineNumber, sizeof(uint), in); 21 | ct_read(&numOfMemOps, sizeof(uint), in); 22 | ct_read(&numOps, sizeof(uint), in); 23 | ct_read(&critPathLen, sizeof(uint), in); 24 | 25 | ct_read(&strLen, sizeof(uint), in); 26 | if (strLen > 0) 27 | { 28 | f = (char*) malloc(sizeof(char) * (strLen + 8)); 29 | f[strLen] = '\0'; 30 | ct_read(f, sizeof(char) * strLen, in); 31 | function.assign(f); 32 | free(f); 33 | } 34 | 35 | ct_read(&strLen, sizeof(uint), in); 36 | if (strLen > 0) 37 | { 38 | f = (char*) malloc(sizeof(char) * (strLen + 8)); 39 | f[strLen] = '\0'; 40 | ct_read(f, sizeof(char) * strLen, in); 41 | file.assign(f); 42 | free(f); 43 | } 44 | 45 | ct_read(&strLen, sizeof(uint), in); 46 | if (strLen > 0) 47 | { 48 | f = (char*) malloc(sizeof(char) * (strLen + 8)); 49 | f[strLen] = '\0'; 50 | ct_read(f, sizeof(char) * strLen, in); 51 | callsFunction.assign(f); 52 | free(f); 53 | } 54 | 55 | addRawBasicBlockInfo(bbid, flags, lineNumber, numOfMemOps, numOps, critPathLen, function, file, callsFunction); 56 | } 57 | } 58 | 59 | TaskGraphInfo::TaskGraphInfo() 60 | { 61 | 62 | } 63 | 64 | void TaskGraphInfo::addRawBasicBlockInfo(uint bbid, 65 | uint flags, 66 | uint lineNum, 67 | uint numMemOps, 68 | uint numOps, 69 | uint critPathLen, 70 | string function, 71 | string file, 72 | string inokFun) 73 | { 74 | BasicBlockInfo bbi; 75 | 76 | bbi.flags = flags; 77 | bbi.lineNumber = lineNum; 78 | bbi.numOfMemOps = numMemOps; 79 | bbi.numOfOps = numOps; 80 | bbi.critPathLen = critPathLen; 81 | bbi.functionName = function; 82 | bbi.fileName = file; 83 | bbi.callsFunction = inokFun; 84 | 85 | bbInfo[bbid] = bbi; 86 | } 87 | 88 | void TaskGraphInfo::writeTaskGraphInfo(FILE* out) 89 | { 90 | int numBasicBlock = bbInfo.size(); 91 | ct_write(&numBasicBlock, sizeof(int), out); 92 | for (auto it = bbInfo.begin(), et = bbInfo.end(); it != et; ++it) 93 | { 94 | uint strLen; 95 | uint bbid = it->first; 96 | ct_write(&bbid, sizeof(uint), out); 97 | ct_write(&it->second.flags, sizeof(uint), out); 98 | ct_write(&it->second.lineNumber, sizeof(uint), out); 99 | ct_write(&it->second.numOfMemOps, sizeof(uint), out); 100 | ct_write(&it->second.numOfOps, sizeof(uint), out); 101 | ct_write(&it->second.critPathLen, sizeof(uint), out); 102 | 103 | strLen = it->second.functionName.length(); 104 | ct_write(&strLen, sizeof(uint), out); 105 | ct_write(it->second.functionName.c_str(), sizeof(char) * strLen, out); 106 | 107 | strLen = it->second.fileName.length(); 108 | ct_write(&strLen, sizeof(uint), out); 109 | ct_write(it->second.fileName.c_str(), sizeof(char) * strLen, out); 110 | 111 | strLen = it->second.callsFunction.length(); 112 | ct_write(&strLen, sizeof(uint), out); 113 | ct_write(it->second.callsFunction.c_str(), sizeof(char) * strLen, out); 114 | } 115 | } 116 | 117 | BasicBlockInfo& TaskGraphInfo::getBasicBlockInfo(uint bbid) 118 | { 119 | static BasicBlockInfo bbi; 120 | bbi.lineNumber = ~0x0; 121 | auto it = bbInfo.find(bbid); 122 | if (it == bbInfo.end()) return bbi; 123 | return it->second; 124 | } 125 | -------------------------------------------------------------------------------- /common/taskLib/TaskGraphInfo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TASK_GRAPH_INFO_HPP 2 | #define TASK_GRAPH_INFO_HPP 3 | 4 | #include "TaskId.hpp" 5 | #include "Action.hpp" 6 | #include "ct_file.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | namespace contech { 20 | 21 | #define BBI_FLAG_CONTAIN_CALL 0x1 22 | #define BBI_FLAG_CONTAIN_GLOBAL_ACCESS 0x2 23 | 24 | class BasicBlockInfo 25 | { 26 | public: 27 | uint lineNumber; 28 | uint numOfMemOps; 29 | uint numOfOps; 30 | uint critPathLen; 31 | uint flags; 32 | string functionName; 33 | string fileName; 34 | string callsFunction; 35 | //vector typeOfMemOps; 36 | }; 37 | 38 | class FunctionInfo 39 | { 40 | public: 41 | string functionName; 42 | vector typeOfArguments; 43 | uint returnType; 44 | }; 45 | 46 | class TypeInfo 47 | { 48 | string typeName; 49 | size_t sizeOfType; 50 | }; 51 | 52 | class TaskGraphInfo 53 | { 54 | private: 55 | map bbInfo; 56 | //map tyInfo; 57 | //map funInfo; 58 | //map fileName; 59 | 60 | public: 61 | void initTaskGraphInfo(FILE*); 62 | TaskGraphInfo(); 63 | 64 | void addRawBasicBlockInfo(uint bbid, uint flags, uint lineNum, uint numMemOps, uint numOps, uint critPathLen, string function, string file, string); 65 | void writeTaskGraphInfo(FILE*); 66 | 67 | BasicBlockInfo& getBasicBlockInfo(uint bbid); 68 | }; 69 | 70 | } 71 | 72 | #endif -------------------------------------------------------------------------------- /common/taskLib/TaskId.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TASK_ID_HPP 2 | #define TASK_ID_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace contech { 9 | 10 | class ContextId 11 | { 12 | private: 13 | uint32_t id; 14 | public: 15 | ContextId() : id(0) {} 16 | ContextId(uint32_t id_) : id(id_) {} 17 | explicit operator uint32_t() const { return id; } 18 | bool operator==(const ContextId& rhs) const { return id == rhs.id; } 19 | bool operator!=(const ContextId& rhs) const { return id != rhs.id; } 20 | bool operator<(const ContextId& rhs) const { return id < rhs.id; } 21 | bool operator>(const ContextId& rhs) const { return id > rhs.id; } 22 | bool operator>=(const ContextId& rhs) const { return id >= rhs.id; } 23 | bool operator<=(const ContextId& rhs) const { return id <= rhs.id; } 24 | friend class TaskId; 25 | std::string toString() const { return std::to_string(id); } 26 | }; 27 | inline static std::ostream& operator<<(std::ostream& os, const ContextId& i) { os << i.toString(); return os; } 28 | 29 | class SeqId 30 | { 31 | private: 32 | uint32_t id; 33 | public: 34 | SeqId() : id(0) {} 35 | SeqId(uint32_t id_) : id(id_) {} 36 | explicit operator uint32_t() const { return id; } 37 | SeqId getNext() const { return SeqId(id + 1); } 38 | bool operator==(const SeqId& rhs) const { return id == rhs.id; } 39 | bool operator!=(const SeqId& rhs) const { return id != rhs.id; } 40 | bool operator<(const SeqId& rhs) const { return id < rhs.id; } 41 | bool operator>(const SeqId& rhs) const { return id > rhs.id; } 42 | bool operator>=(const SeqId& rhs) const { return id >= rhs.id; } 43 | bool operator<=(const SeqId& rhs) const { return id <= rhs.id; } 44 | friend class TaskId; 45 | std::string toString() const { return std::to_string(id); } 46 | }; 47 | inline static std::ostream& operator<<(std::ostream& os, const SeqId& i) { os << i.toString(); return os; } 48 | 49 | class TaskId 50 | { 51 | private: 52 | uint64_t id; 53 | public: 54 | TaskId() : id(0) {} 55 | TaskId(uint64_t id_) : id(id_) {} 56 | TaskId(ContextId cid, SeqId sid) : id((uint64_t)cid.id<<32 | sid.id) {} 57 | explicit operator uint64_t() const { return id; } 58 | ContextId getContextId() const { return ContextId(id>>32); } 59 | SeqId getSeqId() const { return SeqId((uint32_t)id); } 60 | TaskId getNext() const { return TaskId(id + 1); } 61 | bool operator==(const TaskId& rhs) const { return id == rhs.id; } 62 | bool operator!=(const TaskId& rhs) const { return id != rhs.id; } 63 | bool operator<(const TaskId& rhs) const { return id < rhs.id; } 64 | bool operator>(const TaskId& rhs) const { return id > rhs.id; } 65 | bool operator>=(const TaskId& rhs) const { return id >= rhs.id; } 66 | bool operator<=(const TaskId& rhs) const { return id <= rhs.id; } 67 | friend class std::hash; 68 | std::string toString() const { return getContextId().toString() + ":" + getSeqId().toString(); } 69 | }; 70 | inline static std::ostream& operator<<(std::ostream& os, const TaskId& i) { os << i.toString(); return os; } 71 | 72 | } // end namespace contech 73 | 74 | // overload std::hash for TaskId so it can be used in hash maps 75 | namespace std 76 | { 77 | template <> 78 | struct hash 79 | { 80 | typedef size_t result_type; 81 | typedef contech::TaskId argument_type; 82 | 83 | result_type operator()(contech::TaskId const & in) const noexcept 84 | { 85 | return hash()(in.id); 86 | } 87 | }; 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /common/taskLib/ct_file.c: -------------------------------------------------------------------------------- 1 | #include "ct_file.h" 2 | #include 3 | #include 4 | #include 5 | 6 | size_t ct_read(void * ptr, size_t size, FILE* handle) 7 | { 8 | size_t read = 0; 9 | 10 | do { 11 | size_t r = fread((char*)ptr + read, 1, size - read, handle); 12 | read += r * 1; // fread returns the number of items read 13 | if ((r == 0) && (feof(handle) != 0)) break; 14 | } while (read < size); 15 | 16 | return read; 17 | } 18 | 19 | 20 | size_t ct_write(const void * ptr, size_t size, FILE* handle) 21 | { 22 | size_t written = 0; 23 | 24 | do { 25 | size_t w = fwrite((char*)ptr + written, 1, size - written, handle); 26 | written += w * 1; 27 | } while (written < size); 28 | return written; 29 | } 30 | -------------------------------------------------------------------------------- /common/taskLib/ct_file.h: -------------------------------------------------------------------------------- 1 | #ifndef CT_FILE_H 2 | #define CT_FILE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(__cplusplus) 11 | extern "C" 12 | { 13 | #endif 14 | 15 | //wrapper to read from a ct_file handle. Abstracts the details of compressesion 16 | size_t ct_read(void * ptr, size_t size, FILE* handle); 17 | 18 | //wrapper to write to a ct_file handle. Abstracts the details of compression 19 | size_t ct_write(const void * ptr, size_t size, FILE* handle); 20 | 21 | #if defined(__cplusplus) 22 | } 23 | #endif 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /ct_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bprail/contech/62f8db32b65b19c8c5a37f72d75c6ece94acddf6/ct_logo.png -------------------------------------------------------------------------------- /llvm-contech/.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles/ 3 | Makefile 4 | cmake_install.cmake 5 | install_manifest.txt 6 | lib/ 7 | -------------------------------------------------------------------------------- /llvm-contech/BufferCheckAnalysis.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BUFFER_CHECK_ANALYSIS_H__ 3 | #define __BUFFER_CHECK_ANALYSIS_H__ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "llvm/Support/raw_ostream.h" 16 | #include "llvm/ADT/BitVector.h" 17 | #include "llvm/ADT/DenseMap.h" 18 | #include "llvm/IR/ValueMap.h" 19 | #include "llvm/IR/CFG.h" 20 | 21 | 22 | #include "llvm/Analysis/LoopInfo.h" 23 | #include "llvm/Analysis/ValueTracking.h" 24 | #include "llvm/IR/Instruction.h" 25 | #include "llvm/Pass.h" 26 | #include "llvm/Analysis/LoopPass.h" 27 | #include "llvm/Support/raw_ostream.h" 28 | #include "llvm/Support/Casting.h" 29 | #include "llvm/IR/IntrinsicInst.h" 30 | #include "llvm/Transforms/Utils/LoopUtils.h" 31 | 32 | #include "ContechDef.h" 33 | 34 | using namespace llvm; 35 | using namespace std; 36 | 37 | namespace llvm { 38 | 39 | class BufferCheckAnalysis 40 | { 41 | public: 42 | BufferCheckAnalysis(map&, 43 | map&, 44 | map&, 45 | unordered_map&, int); 46 | ~BufferCheckAnalysis() {} 47 | // the flow analysis components 48 | int copy(int); 49 | // the analysis usage 50 | void runAnalysis(Function*); 51 | // helper function 52 | void prettyPrint(); 53 | 54 | map getNeedCheckAtBlock() const { return needCheckAtBlock; } 55 | 56 | bool hasStateChange(map&, map&); 57 | map> getStateAfter() const { return stateAfter; } 58 | private: 59 | // analysis parameter 60 | const int DEFAULT_SIZE{ 1024 }; 61 | const int FUNCTION_REMAIN; 62 | const int LOOP_EXIT_REMAIN; 63 | 64 | hash blockHash; 65 | 66 | map needCheckAtBlock; 67 | 68 | map blockInfo; 69 | map loopExits; 70 | map loopBelong; 71 | unordered_map loopEntry; 72 | map> stateAfter; 73 | 74 | int flowFunction(int, BasicBlock*); 75 | int getMemUsed(BasicBlock*); 76 | int getLoopPath(Loop*); 77 | int accumulateBranch(vector&); 78 | }; 79 | 80 | } 81 | 82 | #endif -------------------------------------------------------------------------------- /llvm-contech/BufferSizeAnalysis.cpp.bak: -------------------------------------------------------------------------------- 1 | 2 | #include "BufferSizeAnalysis.h" 3 | 4 | using namespace llvm; 5 | using namespace std; 6 | 7 | namespace llvm { 8 | 9 | BufferSizeAnalysis::BufferSizeAnalysis(map& blockMemOps_, 10 | map& blockElide_, 11 | map& loopExits_, 12 | map& loopBelong_, 13 | unordered_map& loopEntry_) : 14 | blockMemOps{ blockMemOps_ }, 15 | blockElide{ blockElide_ }, 16 | loopExits{ loopExits_ }, 17 | loopBelong{ loopBelong_ }, 18 | loopEntry{ loopEntry_ } 19 | {} 20 | 21 | int BufferSizeAnalysis::getMemUsed(int bb_val) 22 | { 23 | bool isElide = blockElide[bb_val]; 24 | int memCnt = blockMemOps[bb_val]; 25 | 26 | return (6 * memCnt) + (isElide ? 0 : 3); 27 | } 28 | 29 | // get the number of bytes used with a loop interation 30 | int BufferSizeAnalysis::getLoopPath(Loop* lp) 31 | { 32 | int cnt = 0; 33 | for (auto BIt = lp->block_begin(), BEIt = lp->block_end(); BIt != BEIt; ++BIt) { 34 | BasicBlock* B = *BIt; 35 | int bb_val = blockHash(B); 36 | cnt += getMemUsed(bb_val); 37 | } 38 | 39 | return cnt; 40 | } 41 | 42 | // see if the basic block is the exit 43 | // of a diamond pattern 44 | bool BufferSizeAnalysis::isPatternExit(BasicBlock* bb) 45 | { 46 | int bb_val = blockHash(bb); 47 | return (bb->getTerminator()->getNumSuccessors() > 1) && 48 | loopBelong.find(bb_val) == loopBelong.end(); 49 | } 50 | 51 | // see if the basic block if a valid candidate 52 | // of a diamond pattern 53 | bool BufferSizeAnalysis::isValidBlock(BasicBlock* bb) 54 | { 55 | int bb_val = blockHash(bb); 56 | 57 | // it should only have a single successor 58 | if (bb->getTerminator()->getNumSuccessors() > 1) { 59 | return false; 60 | } 61 | // it should not belongs to any loop 62 | if (loopBelong.find(bb_val) != loopBelong.end()) { 63 | return false; 64 | } 65 | // there should be no function call 66 | Instruction* last = &*(bb->end()); 67 | for (auto I = bb->begin(); I != bb->end(); ++I) { 68 | Instruction* inst = &*I; 69 | if (CallInst* CI = dyn_cast(inst)) { 70 | Function* called_function = CI->getCalledFunction(); 71 | if (called_function == nullptr || 72 | !called_function->isDeclaration()) { 73 | return false; 74 | } 75 | } 76 | } 77 | 78 | return true; 79 | } 80 | 81 | // calculate the total number of bytes within a sequence of 82 | // basic blocks within the diamond pattern 83 | int BufferSizeAnalysis::calculateLinePath(vector& blockLines) 84 | { 85 | int sum = 0; 86 | for (int bb_val : blockLines) { 87 | sum += getMemUsed(bb_val); 88 | } 89 | return sum; 90 | } 91 | 92 | // see if the basic block is the beginning of a 93 | // diamond pattern 94 | bool BufferSizeAnalysis::isPatternEntry(BasicBlock* bb) 95 | { 96 | int bb_val = blockHash(bb); 97 | return loopExits.find(bb_val) != loopExits.end(); 98 | } 99 | 100 | // collect all basic blocks within a diamond pattern 101 | void BufferSizeAnalysis::accumulatePath(BasicBlock* bb, 102 | vector& patterns) 103 | { 104 | // while it belongs to a pattern 105 | // add to the pattern set 106 | while (isValidBlock(bb) && bb->getTerminator()->getNumSuccessors() > 0) { 107 | outs() << "loops\n"; 108 | int bb_val = blockHash(bb); 109 | patterns.push_back(bb_val); 110 | if (bb->getTerminator()->getNumSuccessors() == 1) { 111 | bb = *succ_begin(bb); 112 | } 113 | } 114 | // if it is exit of a function 115 | // or a pattern exit 116 | // also append to the pattern set 117 | if (isPatternExit(bb) || bb->getTerminator()->getNumSuccessors() == 0) { 118 | int bb_val = blockHash(bb); 119 | patterns.push_back(bb_val); 120 | } 121 | } 122 | 123 | 124 | int BufferSizeAnalysis::runAnalysis(Function* fblock) 125 | { 126 | // check all if after loop path 127 | // length and get its maximum 128 | int max_loop_path = 0; 129 | for (auto B = fblock->begin(); B != fblock->end(); ++B) { 130 | BasicBlock* bb = &*B; 131 | int bb_val = blockHash(bb); 132 | //vector straightBlocks{}; 133 | vector straightBlocks{}; 134 | // bb is the begin block 135 | // this returns the longest straight basic blocks path 136 | // each block should only have one successor 137 | // b1 -> b2 -> ... -> bn 138 | if (isPatternEntry(bb)) { 139 | for (auto NB = succ_begin(bb); NB != succ_end(bb); ++NB) { 140 | BasicBlock* next_bb = *NB; 141 | int next_bb_val = blockHash(next_bb); 142 | if (isPatternExit(next_bb)) { 143 | straightBlocks.push_back(bb_val); 144 | straightBlocks.push_back(next_bb_val); 145 | break; 146 | } 147 | else if (isValidBlock(next_bb)) { 148 | straightBlocks.push_back(bb_val); 149 | accumulatePath(next_bb, straightBlocks); 150 | break; 151 | } 152 | } 153 | } 154 | int line_path = calculateLinePath(straightBlocks); 155 | if (max_loop_path < line_path) { 156 | max_loop_path = line_path; 157 | } 158 | } 159 | return max_loop_path; 160 | } 161 | } -------------------------------------------------------------------------------- /llvm-contech/BufferSizeAnalysis.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_SIZE_ANALYSIS_H__ 2 | #define __BUFFER_SIZE_ANALYSIS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include "llvm/Support/raw_ostream.h" 15 | #include "llvm/ADT/BitVector.h" 16 | #include "llvm/ADT/DenseMap.h" 17 | #include "llvm/IR/ValueMap.h" 18 | #include "llvm/IR/CFG.h" 19 | 20 | 21 | #include "llvm/Analysis/LoopInfo.h" 22 | #include "llvm/Analysis/ValueTracking.h" 23 | #include "llvm/IR/Instruction.h" 24 | #include "llvm/Pass.h" 25 | #include "llvm/Analysis/LoopPass.h" 26 | #include "llvm/Support/raw_ostream.h" 27 | #include "llvm/Support/Casting.h" 28 | #include "llvm/IR/IntrinsicInst.h" 29 | #include "llvm/Transforms/Utils/LoopUtils.h" 30 | 31 | using namespace llvm; 32 | using namespace std; 33 | 34 | namespace llvm { 35 | 36 | class BufferSizeAnalysis 37 | { 38 | public: 39 | BufferSizeAnalysis(map& blockMemOps, 40 | map& blockElide, 41 | map& loopExits, 42 | map& loopBelong, 43 | unordered_map& loopEntry); 44 | ~BufferSizeAnalysis() {} 45 | 46 | int runAnalysis(Function*); 47 | int getMemUsed(int); 48 | int getLoopPath(Loop*); 49 | bool isValidBlock(BasicBlock*); 50 | int calculateLinePath(vector& blockLines); 51 | void accumulatePath(BasicBlock* bb, vector&); 52 | bool isPatternEntry(BasicBlock*); 53 | bool isPatternExit(BasicBlock*); 54 | private: 55 | std::hash blockHash; 56 | 57 | std::map blockMemOps; 58 | std::map blockElide; 59 | std::map loopExits; 60 | std::map loopBelong; 61 | std::unordered_map loopEntry; 62 | }; 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /llvm-contech/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | find_package(LLVM REQUIRED CONFIG) 3 | 4 | list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") 5 | include(AddLLVM) 6 | 7 | add_definitions(${LLVM_DEFINITIONS}) 8 | include_directories(${LLVM_INCLUDE_DIRS}) 9 | 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g") 11 | 12 | # AddLLVM needs these 13 | set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) 14 | set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) 15 | 16 | include(HandleLLVMOptions) # important: matches compiler flags to LLVM/Clang build 17 | include(AddLLVM) 18 | #add_library(LLVMContech MODULE Contech.cpp) 19 | 20 | add_llvm_loadable_module( LLVMContech 21 | Contech.cpp 22 | BufferCheckAnalysis.cpp 23 | LoopIV.cpp 24 | Path.cpp 25 | Support.cpp 26 | ) 27 | 28 | target_link_libraries(LLVMContech) 29 | -------------------------------------------------------------------------------- /llvm-contech/Contech.exports: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bprail/contech/62f8db32b65b19c8c5a37f72d75c6ece94acddf6/llvm-contech/Contech.exports -------------------------------------------------------------------------------- /llvm-contech/LoopIV.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOOP_H 2 | #define _LOOP_H 3 | 4 | #include "llvm/IR/Function.h" 5 | #include "llvm/Analysis/LoopInfo.h" 6 | #include "llvm/Analysis/LoopPass.h" 7 | #include "llvm/Analysis/ValueTracking.h" 8 | #include "llvm/Pass.h" 9 | #include "llvm/Support/raw_ostream.h" 10 | #include "llvm/IR/InstIterator.h" 11 | #include "llvm/IR/Instruction.h" 12 | #include "llvm/IR/Instructions.h" 13 | #include "llvm/IR/IntrinsicInst.h" 14 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 15 | #include "llvm/IR/Type.h" 16 | #include "llvm/IR/Value.h" 17 | #include "llvm/ADT/SmallVector.h" 18 | 19 | #include "llvm/Analysis/LoopInfo.h" 20 | #include "llvm/Analysis/ScalarEvolution.h" 21 | #include "llvm/Analysis/ScalarEvolutionExpressions.h" 22 | #include "llvm/IR/GetElementPtrTypeIterator.h" 23 | 24 | #include "ContechDef.h" 25 | 26 | using namespace llvm; 27 | using namespace std; 28 | 29 | namespace llvm { 30 | typedef vector SmallInstructionVector; 31 | typedef vector LlvmLoopIVBlockVector; 32 | 33 | class LoopIV { 34 | 35 | public: 36 | LoopIV(Contech* _ctThis) { 37 | ctThis = _ctThis; 38 | } 39 | void collectPossibleIVs(Loop *L); 40 | void collectDerivedIVs(Loop *L, SmallInstructionVector IVs, SmallInstructionVector *DerivedIvs); 41 | virtual bool runOnFunction (Function &F); 42 | LlvmLoopIVBlockVector getLoopMemoryOps(); 43 | 44 | private: 45 | Contech* ctThis; 46 | bool isLoopControlIV(Loop *L, Instruction *IV); 47 | void iterateOnLoop(Loop *L, Loop*); 48 | bool verifyLoopCTInvariant(Loop*); 49 | const SCEVConstant *getIncrmentFactorSCEV(ScalarEvolution *SE, const SCEV *SCEVExpr, Instruction &IV); 50 | Value* collectPossibleMemoryOps(GetElementPtrInst* gepAddr, SmallInstructionVector IVs, bool is_derived, Loop*, std::vector&); 51 | Value* inferredMemoryOps(GetElementPtrInst* gepAddr, bool is_derived, Loop* L, llvm_loopiv_block &llb); 52 | Value* isAddOrPHIConstant(Value*, bool); 53 | }; 54 | } 55 | #endif -------------------------------------------------------------------------------- /llvm-contech/README: -------------------------------------------------------------------------------- 1 | This directory is provides for the ongoing development of the Contech 2 | instrumentation pass as operates with LLVM 3.8+. 3 | 4 | As LLVM continues to evolve its APIs, the Contech pass has become increasingly 5 | brittle as it tries to target 3.2 through 3.7. With 3.9, cmake will also 6 | be required and therefore this pass version will also have this requirement. 7 | 8 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/Contech/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_loadable_module( LLVMContech 2 | Contech.cpp 3 | ) 4 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/Contech/Contech.exports: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bprail/contech/62f8db32b65b19c8c5a37f72d75c6ece94acddf6/llvm/lib/Transforms/Contech/Contech.exports -------------------------------------------------------------------------------- /llvm/lib/Transforms/Contech/Makefile: -------------------------------------------------------------------------------- 1 | ##===- lib/Transforms/Contech/Makefile -----------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | LEVEL = ../../.. 11 | LIBRARYNAME = LLVMContech 12 | LOADABLE_MODULE = 1 13 | USEDLIBS = 14 | 15 | ifneq ($(REQUIRES_RTTI), 1) 16 | ifneq ($(REQUIRES_EH), 1) 17 | EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/Contech.exports 18 | endif 19 | endif 20 | 21 | include $(LEVEL)/Makefile.common 22 | 23 | LIB = $(LIB) 24 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/DynamicAnalysis/DynamicAnalysis.exports: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bprail/contech/62f8db32b65b19c8c5a37f72d75c6ece94acddf6/llvm/lib/Transforms/DynamicAnalysis/DynamicAnalysis.exports -------------------------------------------------------------------------------- /llvm/lib/Transforms/DynamicAnalysis/Makefile: -------------------------------------------------------------------------------- 1 | ##===- lib/Transforms/Contech/Makefile -----------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | LEVEL = ../../.. 11 | LIBRARYNAME = LLVMDynamicAnalysis 12 | LOADABLE_MODULE = 1 13 | USEDLIBS = Task.a 14 | 15 | ifneq ($(REQUIRES_RTTI), 1) 16 | ifneq ($(REQUIRES_EH), 1) 17 | EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/DynamicAnalysis.exports 18 | endif 19 | endif 20 | 21 | include $(LEVEL)/Makefile.common 22 | 23 | LIB = $(LIB) 24 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/DynamicAnalysis/Params.h: -------------------------------------------------------------------------------- 1 | #include "llvm/ADT/APInt.h" 2 | #include "llvm/ADT/Statistic.h" 3 | #include "llvm/CodeGen/IntrinsicLowering.h" 4 | #include "llvm/IR/Constants.h" 5 | #include "llvm/IR/DerivedTypes.h" 6 | #include "llvm/IR/Instructions.h" 7 | #include "llvm/Support/CommandLine.h" 8 | #include "llvm/Support/Debug.h" 9 | #include "llvm/Support/ErrorHandling.h" 10 | #include "llvm/Support/GetElementPtrTypeIterator.h" 11 | #include "llvm/Support/MathExtras.h" 12 | #include "llvm/Pass.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "llvm/IR/Module.h" 19 | #include 20 | 21 | //VCA 22 | #include "DynamicAnalysis.h" 23 | 24 | 25 | static cl::opt PrintVolatile("interpreter-print-volatile", cl::Hidden, 26 | cl::desc("make the interpreter print every volatile load and store")); 27 | 28 | 29 | //===----------------------------------------------------------------------===// 30 | // VCA: Command line options for application analysis 31 | // 32 | // Command line documentation:http://llvm.org/docs/CommandLine.html 33 | //===----------------------------------------------------------------------===// 34 | static cl::opt PerTaskCommFactor("per-task-comm-factor", cl::desc("Use per task comm factors. Default FALSE"), cl::init(false)); 35 | 36 | static cl::opt CommFactorRead("comm-factor-read", cl::desc("Communication probability factor to scale cache read latency, default 0"), cl::init(0)); 37 | 38 | static cl::opt CommFactorWrite("comm-factor-write", cl::desc("Communication probability factor to scale cache write latency, default 0"), cl::init(0)); 39 | 40 | static cl::opt ContextNumber("context-number", cl::desc("Context # to be analyzed, default 0"), cl::init(0)); 41 | 42 | static cl::opt MemoryWordSize("memory-word-size", cl::desc("Specify the size in bytes of a data item. Default value is 8 (double precision)"),cl::init(8)); 43 | 44 | static cl::opt CacheLineSize("cache-line-size", cl::desc("Specify the cache line size (B). Default value is 64 B"),cl::init(64)); 45 | 46 | static cl::opt L1CacheSize("l1-cache-size", cl::desc("Specify the size of the L1 cache (in bytes). Default value is 32 KB"),cl::init(32768)); 47 | 48 | static cl::opt L2CacheSize("l2-cache-size", cl::desc("Specify the size of the L2 cache (in bytes). Default value is 256 KB"),cl::init(262144)); 49 | 50 | static cl::opt LLCCacheSize("llc-cache-size", cl::desc("Specify the size of the L3 cache (in bytes). Default value is 20 MB"),cl::init(20971520)); 51 | 52 | 53 | static cl::opt Microarchitecture("uarch", cl::desc("Name of the microarchitecture"), 54 | cl::init("SB")); 55 | 56 | static cl::list ExecutionUnitsLatency("execution-units-latency", cl::CommaSeparated, cl::desc("Specify the execution latency of the nodes(cycles). Default value is 1 cycle")); 57 | 58 | 59 | static cl::list ExecutionUnitsThroughput("execution-units-throughput", cl::CommaSeparated, cl::desc("Specify the execution bandwidth of the nodes(ops executed/cycles). Default value is -1 cycle")); 60 | 61 | static cl::list ExecutionUnitsParallelIssue("execution-units-parallel-issue", cl::CommaSeparated, cl::desc("Specify the number of nodes that can be executed in parallel based on ports execution. Default value is -1 cycle")); 62 | 63 | static cl::list MemAccessGranularity("mem-access-granularity", cl::CommaSeparated, cl::desc("Specify the memory access granularity for the different levels of the memory hierarchy (bytes). Default value is memory word size")); 64 | 65 | static cl::opt IFB("instruction-fetch-bandwidth", cl::desc("Specify the size of the reorder buffer. Default value is infinity"),cl::init(-1)); 66 | 67 | static cl::opt ReservationStation("reservation-station-size", cl::desc("Specify the size of a centralized reservation station. Default value is infinity"),cl::init(0)); 68 | 69 | static cl::opt ReorderBuffer("reorder-buffer-size", cl::desc("Specify the size of the reorder buffer. Default value is infinity"),cl::init(0)); 70 | 71 | static cl::opt LoadBuffer("load-buffer-size", cl::desc("Specify the size of the load buffer. Default value is infinity"),cl::init(0)); 72 | 73 | static cl::opt StoreBuffer("store-buffer-size", cl::desc("Specify the size of the store buffer. Default value is infinity"),cl::init(0)); 74 | 75 | static cl::opt LineFillBuffer("line-fill-buffer-size", cl::desc("Specify the size of the fill line buffer. Default value is infinity"),cl::init(0)); 76 | 77 | static cl::opt < bool > ReportOnlyPerformance("report-only-performance", cl::Hidden, cl::desc("Reports only performance (op count and span)"),cl::init(false)); 78 | 79 | static cl::opt TaskGraphFileName("taskgraph-file", cl::desc("File with Contech Task Graph"), cl::value_desc("filename")); 80 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/DynamicAnalysis/README: -------------------------------------------------------------------------------- 1 | DynamicAnalysis is an abstractd simulation of a microarchitecture using 2 | LLVM IR ops as the ISA. It is driven using a Contech task graph and the 3 | instrumented IR file (.bc). 4 | 5 | The simulator is based on the work of Victoria Caparros (caparrov@inf.ethz.ch) 6 | and was published previously [1]. 7 | 8 | [1] Victoria Caparros and Markus Pueschel. ''Extending the Roofline Model: Bottleneck Analysis with Microarchitectural Constraints'', in IISWC'14. 9 | 10 | -------------------------------------------------------------------------------- /llvm/lib/Transforms/DynamicAnalysis/TBV.cpp: -------------------------------------------------------------------------------- 1 | #include "DynamicAnalysis.h" 2 | 3 | TBV::TBV() 4 | { 5 | //tbv_map.resize(SplitTreeRange); 6 | BitVector.resize(SplitTreeRange * MAX_RESOURCE_VALUE); 7 | e = true; 8 | } 9 | 10 | bool TBV::empty() 11 | { 12 | return e; 13 | } 14 | 15 | void TBV::insert_node(uint64_t key, unsigned bitPosition) 16 | { 17 | key = key % SplitTreeRange; 18 | e = false; 19 | //tbv_map[key].BitVector[bitPosition] = 1; 20 | BitVector[key * MAX_RESOURCE_VALUE + bitPosition] = 1; 21 | } 22 | 23 | void TBV::delete_node(uint64_t key, unsigned bitPosition) 24 | { 25 | key = key % SplitTreeRange; 26 | //tbv_map[key].BitVector[bitPosition] = 0; 27 | BitVector[key * MAX_RESOURCE_VALUE + bitPosition] = 0; 28 | } 29 | 30 | bool TBV::get_node(uint64_t key, unsigned bitPosition) 31 | { 32 | //if (empty()) return false; 33 | key = key % SplitTreeRange; 34 | //return (tbv_map[key].BitVector[bitPosition] == 1); 35 | return (BitVector[key * MAX_RESOURCE_VALUE + bitPosition] == 1); 36 | } 37 | 38 | bool TBV::get_node_nb(uint64_t key, unsigned bitPosition) 39 | { 40 | //if (empty()) return false; 41 | key = key % SplitTreeRange; 42 | //return (tbv_map[key].BitVector[bitPosition] == 0); 43 | return (BitVector[key * MAX_RESOURCE_VALUE + bitPosition] == 0); 44 | } 45 | 46 | uint64_t BitScan(vector< TBV> &FullOccupancyCyclesTree, uint64_t key, unsigned bitPosition) 47 | { 48 | uint64_t kLocal = key % SplitTreeRange; 49 | uint64_t chunk = kLocal / SplitTreeRange; 50 | 51 | while (chunk < FullOccupancyCyclesTree.size()) 52 | { 53 | while (kLocal < SplitTreeRange) 54 | { 55 | if (FullOccupancyCyclesTree[chunk].get_node(kLocal, bitPosition)) return (kLocal + chunk * SplitTreeRange); 56 | kLocal++; 57 | } 58 | kLocal = 0; 59 | chunk++; 60 | } 61 | 62 | return key; 63 | } 64 | -------------------------------------------------------------------------------- /middle/.gitignore: -------------------------------------------------------------------------------- 1 | middle 2 | simple_middle 3 | -------------------------------------------------------------------------------- /middle/BarrierWrapper.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CT_BARRIER_WRAPPER_HPP 2 | #define CT_BARRIER_WRAPPER_HPP 3 | 4 | #include "../common/taskLib/Task.hpp" 5 | #include "../common/eventLib/ct_event.h" 6 | #include 7 | #include 8 | 9 | namespace contech { 10 | 11 | class BarrierWrapper 12 | { 13 | public: 14 | BarrierWrapper(); 15 | Task* onEnter(Task& arrivingTask, ct_tsc_t arrivalTime, ct_addr_t addr); 16 | Task* onExit(Task*, ct_tsc_t exitTime, bool*); 17 | private: 18 | Task* entryBarrierTask; 19 | list exitBarrierTasks; 20 | }; 21 | 22 | } // end namespace contech 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /middle/Context.cpp: -------------------------------------------------------------------------------- 1 | #include "Context.hpp" 2 | #include "taskWrite.hpp" 3 | 4 | using namespace contech; 5 | 6 | Context::Context() 7 | { 8 | tasks.clear(); 9 | } 10 | 11 | // Returns the currently active task 12 | //Task* Context::activeTask() { return this->tasks.front(); } 13 | Task* Context::activeTask() { return this->tasks.rbegin()->second; } 14 | 15 | // 16 | // Which of this context's tasks created cid 17 | // 18 | TaskId Context::getCreator(ContextId cid) 19 | { 20 | TaskId tid; 21 | auto it = creatorMap.find(cid); 22 | if (it == creatorMap.end()) 23 | { 24 | fprintf(stderr, "Failed to find creator for %d in %d\n", (unsigned int) cid, (unsigned int)activeTask()->getContextId()); 25 | tid = activeTask()->getTaskId(); 26 | assert(it != creatorMap.end()); 27 | } 28 | else 29 | { 30 | tid = it->second; 31 | creatorMap.erase(it); 32 | } 33 | 34 | return tid; 35 | } 36 | 37 | // 38 | // Remove the specified task from the list. 39 | // 40 | bool Context::removeTask(Task* t) 41 | { 42 | // Probably better to use rbegin, but erase only takes iterators and not reverse iterators 43 | /*for (auto it = tasks.begin(), et = tasks.end(); it != et; ++it) 44 | { 45 | if (*it == t) {tasks.erase(it); return true;} 46 | }*/ 47 | 48 | if (t->getType() == task_type_join) 49 | { 50 | auto tjit = joinCountMap.find(t->getTaskId()); 51 | assert(tjit == joinCountMap.end() || tjit->second == 0); 52 | } 53 | 54 | auto it = tasks.find(t->getTaskId()); 55 | if (it == tasks.end()) return false; 56 | tasks.erase(it); 57 | 58 | return true; // false; 59 | } 60 | 61 | Task* Context::getTask(TaskId tid) 62 | { 63 | Task* r = NULL; 64 | 65 | // Probably better to use rbegin, but erase only takes iterators and not reverse iterators 66 | /*for (auto it = tasks.begin(), et = tasks.end(); it != et; ++it) 67 | { 68 | r = *it; 69 | if (r->getTaskId() == tid) {return r;} 70 | }*/ 71 | 72 | auto it = tasks.find(tid); 73 | if (it == tasks.end()) return NULL; 74 | return it->second; 75 | 76 | // Is it safe that r is equal to the last element in the list? 77 | return r; 78 | } 79 | 80 | Task* Context::childExits(TaskId childId) 81 | { 82 | ContextId ctid = childId.getContextId(); 83 | auto it = joinMap.find(ctid); 84 | 85 | // Parent hasn't created the join task yet, record a 'cookie' for parent 86 | if (it == joinMap.end()) 87 | { 88 | //joinMap[ctid] = childId; 89 | // Parent finds child via context[ctid].activeTask 90 | return NULL; 91 | } 92 | else 93 | { 94 | Task* r = it->second; 95 | joinMap.erase(it); 96 | joinCountMap[r->getTaskId()] --; 97 | 98 | if (tasks.find(r->getTaskId()) == tasks.end()) 99 | { 100 | printf("Child exiting on task that has already been removed: %s at %d\n", 101 | r->getTaskId().toString().c_str(), joinCountMap[r->getTaskId()]); 102 | assert(0); 103 | } 104 | 105 | return r; 106 | } 107 | } 108 | 109 | void Context::getChildJoin(ContextId ctid, Task* tj) 110 | { 111 | joinMap[ctid] = tj; 112 | joinCountMap[tj->getTaskId()] ++; 113 | } 114 | 115 | bool Context::isCompleteJoin(TaskId tid) 116 | { 117 | auto it = joinCountMap.find(tid); 118 | 119 | if (it == joinCountMap.end()) return true; 120 | if (it->second > 0) return false; 121 | 122 | joinCountMap.erase(it); 123 | 124 | return true; 125 | } 126 | 127 | Task* Context::createBasicBlockContinuation() 128 | { 129 | Task* continuation = new Task(activeTask()->getTaskId().getNext(), task_type_basic_blocks); 130 | continuation->setStartTime(activeTask()->getEndTime()); 131 | // End time will be set by the next continuation 132 | 133 | // Set as continuation of the active task 134 | activeTask()->addSuccessor(continuation->getTaskId()); 135 | continuation->addPredecessor(activeTask()->getTaskId()); 136 | 137 | // Make the continuation active 138 | //tasks.push_front(continuation); 139 | tasks[continuation->getTaskId()] = continuation; 140 | 141 | return continuation; 142 | } 143 | 144 | Task* Context::createContinuation(task_type type, ct_tsc_t tStartTime, ct_tsc_t tEndTime) 145 | { 146 | Task* bbContinue = NULL; 147 | assert(type != task_type_basic_blocks); 148 | //assert(activeTask()->getType() == task_type_basic_blocks); 149 | if (activeTask()->getType() != task_type_basic_blocks) 150 | { 151 | bbContinue = createBasicBlockContinuation(); 152 | } 153 | 154 | // This context has not exited 155 | assert(endTime == 0); 156 | 157 | //assert(startTime >= currentTime && 158 | // endTime >= startTime); 159 | // With OpenMP, the runtime puts in create events on behalf of other contexts 160 | // this can result in reversed timestamps. Stitch them up here. 161 | if (tStartTime < currentTime) 162 | { 163 | ct_tsc_t delta = currentTime - tStartTime; 164 | tStartTime += delta; 165 | tEndTime += delta; 166 | } 167 | currentTime = tEndTime; 168 | 169 | // Set the end time of the previous basic block task 170 | activeTask()->setEndTime(tStartTime); 171 | 172 | // Create the continuation task 173 | Task* continuation = new Task(activeTask()->getTaskId().getNext(), type); 174 | continuation->setStartTime(tStartTime); 175 | continuation->setEndTime(tEndTime); 176 | 177 | // Set as continuation of the active task 178 | activeTask()->addSuccessor(continuation->getTaskId()); 179 | continuation->addPredecessor(activeTask()->getTaskId()); 180 | 181 | // Make the continuation active 182 | //tasks.push_front(continuation); 183 | tasks[continuation->getTaskId()] = continuation; 184 | 185 | if (bbContinue != NULL) 186 | { 187 | removeTask(bbContinue); 188 | backgroundQueueTask(bbContinue); 189 | } 190 | 191 | return continuation; 192 | } 193 | -------------------------------------------------------------------------------- /middle/Context.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CT_CONTECH_HPP 2 | #define CT_CONTECH_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../common/eventLib/ct_event.h" 8 | #include "../common/taskLib/Task.hpp" 9 | 10 | namespace contech { 11 | 12 | class Context 13 | { 14 | 15 | public: 16 | 17 | Context(); 18 | 19 | Task* activeTask(); 20 | Task* createBasicBlockContinuation(); 21 | Task* createContinuation(task_type eventType, ct_tsc_t startTime, ct_tsc_t endTime); 22 | bool removeTask(Task*); 23 | Task* getTask(TaskId); 24 | TaskId getCreator(ContextId); 25 | void getChildJoin(ContextId, Task*); 26 | Task* childExits(TaskId); 27 | bool isCompleteJoin(TaskId); 28 | 29 | // Queue of tasks that are running in this contech but have not been written to file yet. These tasks may have incomplete data. 30 | // The front of the queue represents more recent tasks. 31 | //list tasks; 32 | map tasks; 33 | 34 | // Map of ContextId -> TaskId, which task created which context 35 | map creatorMap; 36 | // Map of child Context -> (childId -or- joinId) 37 | map joinMap; 38 | // How many joins are pending for this task, if 0 and not active then clear 39 | map joinCountMap; 40 | 41 | // Has this contech started running? 42 | bool hasStarted = false; 43 | 44 | // The absolute time when this contech was created. 45 | // -For contech 0, this must be 0 (the start of the first contech marks the beginning of absolute time) 46 | // -For other contechs, this must be set to a non-zero value before any events occur in this contech, so that we can calculate the timeOffset 47 | ct_tsc_t startTime = 0; 48 | 49 | // The absolute time when this contech ended 50 | // Really just a storage place so we can capture the end time of join events 51 | ct_tsc_t endTime = 0; 52 | 53 | // Time offset between absolute time and relative time for this contech 54 | ct_tsc_t timeOffset = 0; 55 | 56 | ct_tsc_t currentTime = 0; 57 | }; 58 | 59 | } // end namespace contech 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /middle/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | PROJECT = middle 3 | OBJECTS = middle.o Context.o BarrierWrapper.o taskWrite.o eventQ.o 4 | CPPFLAGS = -O3 -g --std=c++11 -pthread 5 | LIBS = -lTask -lct_event -lz -Wl,-rpath=$(CONTECH_HOME)/common/taskLib/ 6 | 7 | all: $(PROJECT) 8 | 9 | $(PROJECT): $(OBJECTS) 10 | $(CXX) $(OBJECTS) $(LIBS) -L../common/eventLib/ -L../common/taskLib/ -pthread -o $(PROJECT) 11 | 12 | clean: 13 | rm -f $(PROJECT) $(OBJECTS) 14 | 15 | 16 | -------------------------------------------------------------------------------- /middle/eventQ.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVENT_Q_H 2 | #define EVENT_Q_H 3 | 4 | #include "../common/taskLib/Task.hpp" 5 | #include "../common/eventLib/ct_event.h" 6 | #include 7 | #include 8 | 9 | namespace contech { 10 | 11 | class EventList 12 | { 13 | private: 14 | EventLib* el; 15 | 16 | unsigned long int currentQueuedCount ; 17 | unsigned long int maxQueuedCount ; 18 | unsigned long long ticketNum ; 19 | unsigned long long barrierNum; 20 | unsigned long long minQueuedTicket ; 21 | bool resetMinTicket; 22 | 23 | map > queuedEvents; 24 | map > waitingEvents; 25 | map >::iterator eventQueueCurrent; 26 | 27 | void rescanMinTicket(); 28 | void rescanMinTicketDeep(); 29 | void barrierTicket(); 30 | 31 | public: 32 | EventList(FILE*); 33 | ~EventList(); 34 | pct_event getNextContechEvent(); 35 | void readyEvents(unsigned int); 36 | int mpiRank; 37 | uint64_t getSpace(); 38 | FILE* file; 39 | }; 40 | 41 | class EventQ 42 | { 43 | private: 44 | 45 | deque traces; 46 | deque ::iterator currentTrace; 47 | uint64_t totalSpace; 48 | 49 | public: 50 | EventQ(); 51 | ~EventQ(); 52 | pct_event getNextContechEvent(int*); 53 | void readyEvents(int, unsigned int); 54 | void registerEventList(FILE*); 55 | void printSpaceTime(ct_tsc_t); 56 | }; 57 | 58 | } 59 | 60 | #endif -------------------------------------------------------------------------------- /middle/middle.hpp: -------------------------------------------------------------------------------- 1 | #include "../common/eventLib/ct_event.h" 2 | #include "../common/taskLib/TaskGraph.hpp" 3 | 4 | #include "Context.hpp" 5 | #include "BarrierWrapper.hpp" 6 | #include "eventQ.hpp" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | // Maximum number of contechs (thread contexts) 21 | #define MAX_CONTECHS 1024 22 | 23 | #define MAX_BLOCK_THRESHOLD 10000000 24 | 25 | using namespace contech; 26 | 27 | void checkContextId(ContextId id); 28 | void eventDebugPrint(TaskId first, string verb, TaskId second, ct_tsc_t start, ct_tsc_t end); 29 | 30 | extern ct_tsc_t totalCycles; 31 | 32 | class first_compare 33 | { 34 | public: 35 | bool operator()(pair n1,pair n2) 36 | { 37 | 38 | if(n1.first>n2.first) 39 | return true; 40 | else 41 | return false; 42 | 43 | } 44 | 45 | bool operator()(pair > n1,pair > n2) 46 | { 47 | 48 | if(n1.first>n2.first) 49 | return true; 50 | else 51 | return false; 52 | 53 | } 54 | }; 55 | 56 | struct mpi_recv_req 57 | { 58 | int comm_rank; 59 | int tag; 60 | ct_addr_t buf_ptr; 61 | size_t buf_size; 62 | }; 63 | -------------------------------------------------------------------------------- /middle/output/.gitignore: -------------------------------------------------------------------------------- 1 | *.taskgraph 2 | *.mo 3 | -------------------------------------------------------------------------------- /middle/output/about.txt: -------------------------------------------------------------------------------- 1 | This folder is for holding task graph files that are created by various scripts. 2 | -------------------------------------------------------------------------------- /middle/taskWrite.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TASK_WRITE_HPP 2 | #define TASK_WRITE_HPP 3 | 4 | #include "../common/taskLib/Task.hpp" 5 | #include "Context.hpp" 6 | #include "pthread.h" 7 | #include 8 | 9 | extern bool noMoreTasks; 10 | extern pthread_mutex_t taskQueueLock, taskMemLock; 11 | extern pthread_cond_t taskQueueCond, taskMemCond; 12 | extern std::deque* taskQueue; 13 | 14 | void updateContextTaskList(contech::Context &c); 15 | void attemptBackgroundQueueTask(contech::Task* t, contech::Context &c); 16 | void backgroundQueueTask(contech::Task* t); 17 | 18 | void setROIStart(contech::TaskId); 19 | void setROIEnd(contech::TaskId); 20 | 21 | #endif -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | output 2 | -------------------------------------------------------------------------------- /scripts/batch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | import util 5 | import glob 6 | import json 7 | 8 | 9 | def main(arg): 10 | if len(arg) == 1: 11 | print "Usage: {0} \n".format(arg[0]) 12 | for a in arg[1:]: 13 | launchBackend(a) 14 | 15 | def launchBackend(backend): 16 | CONTECH_HOME = util.findContechInstall() 17 | script = """ 18 | cd /net/tinker/brailing/contech/scripts 19 | 20 | ./run{3}.py --cached {0} -n 16 -i {2} --backend {1} 21 | """ 22 | bset = util.Benchmarks.all 23 | for b in util.Benchmarks.nas: 24 | util.quicksub(name="{}_{}".format(b, backend), code=script.format(b, backend, "A", "_nas"), resources=["nodes=1:ppn=24"], queue="newpasta") 25 | for b in bset: 26 | util.quicksub(name="{}_{}".format(b, backend), code=script.format(b, backend, "simmedium", "_parsec"), resources=["nodes=1:ppn=24"], queue="newpasta") 27 | 28 | 29 | def buildLocal(benchmark): 30 | CONTECH_HOME = util.findContechInstall() 31 | os.chdir(os.path.join(CONTECH_HOME, "scripts")) 32 | try: 33 | util.pcall(["./build_parsec.py {0}".format(benchmark)]) 34 | except: 35 | pass 36 | 37 | def compilationTimeCompare(benchmarks): 38 | CONTECH_HOME = util.findContechInstall() 39 | script = """ 40 | cd $CONTECH_HOME/scripts 41 | 42 | """ 43 | # extract = """grep "Build finished in" | sed s/'Build finished in'/{{\"{0}\":/ | sed s/seconds/}}/""" 44 | label = "sed s/'Build'/'{0}'/ " 45 | 46 | for benchmark in benchmarks: 47 | test = """ 48 | # {0} 49 | ./build_parsec.py {0} --bldconf llvm | {1} 50 | ./build_parsec.py {0} --bldconf contech | {2} 51 | 52 | """ 53 | script += test.format(benchmark, label.format(benchmark+"-llvm"), label.format(benchmark+"-contech")) 54 | 55 | # print script 56 | return util.quicksub(name=("timed_compilation"), code=script) 57 | 58 | def build(benchmark, bldconf="contech"): 59 | 60 | CONTECH_HOME = util.findContechInstall() 61 | script = """ 62 | cd $CONTECH_HOME/scripts 63 | 64 | ./build_parsec.py {0} --bldconf {1} 65 | """ 66 | script = script.format(benchmark, bldconf) 67 | return util.quicksub(name=("build_" + benchmark), code=script) 68 | 69 | def mark(benchmark): 70 | 71 | CONTECH_HOME = util.findContechInstall() 72 | script = """ 73 | cd $CONTECH_HOME/scripts 74 | 75 | ./mark_parsec.py {0} 76 | """ 77 | script = script.format(benchmark) 78 | return util.quicksub(name=("mark_" + benchmark), code=script) 79 | 80 | def nativeRun(benchmark, n, input): 81 | 82 | PARSEC_HOME = util.findParsecInstall() 83 | script = """ 84 | $PARSEC_HOME/bin/parsecmgmt -a run -p {0} -c llvm -n {1} -i {2} -s "/usr/bin/time" 85 | """ 86 | script = script.format(benchmark, n, input) 87 | jobName = "llvm_{}_{}_{}".format(input, n, benchmark) 88 | print jobName 89 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24"], queue="newpasta") 90 | 91 | def statsRun(benchmark, n, input, option): 92 | 93 | CONTECH_HOME = util.findContechInstall() 94 | script = """ 95 | cd $CONTECH_HOME/scripts 96 | 97 | ./run_parsec.py {0} -n {1} -i {2} {3} --backends stats 98 | rm -f --verbose /tmp/{0}.contech.trace 99 | rm -f --verbose /tmp/{0}.taskgraph; 100 | """ 101 | options = {"discard": "--discardTrace", 102 | "pin" : "--pinFrontend", 103 | "contech" : "", 104 | "contechmarker" : ""} 105 | 106 | script = script.format(benchmark, n, input, options[option]) 107 | jobName = "{}_{}_{}_{}".format(option, input, n, benchmark) 108 | print jobName 109 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24"], queue="newpasta") 110 | 111 | 112 | if __name__ == "__main__": 113 | main(sys.argv) 114 | -------------------------------------------------------------------------------- /scripts/build_nas.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import argparse 5 | import subprocess 6 | import shutil 7 | from util import pcall, Timer 8 | import util 9 | 10 | def main(): 11 | parser = argparse.ArgumentParser(description="Builds a nas benchmark with contech") 12 | parser.add_argument("benchmark", help="The nas benchmark to build.") 13 | parser.add_argument("-i", "--input", help="The input size to use.", default="S") 14 | parser.add_argument("-c", "--config", help="The configuration to use.", default="contech") 15 | 16 | args = parser.parse_args() 17 | 18 | if os.environ.has_key("CONTECH_HOME"): 19 | CONTECH_HOME = os.environ["CONTECH_HOME"] 20 | stateFile = os.path.join(CONTECH_HOME, "scripts/output/", args.benchmark + ".stateFile.temp") 21 | os.environ["CONTECH_STATE_FILE"] = stateFile 22 | else: 23 | print ">Error: Could not find contech installation. Set CONTECH_HOME to the root of your contech directory." 24 | exit(1) 25 | 26 | if os.environ.has_key("NAS_HOME"): 27 | NAS_HOME = os.environ["NAS_HOME"] 28 | else: 29 | print ">Error: Could not find NAS installation. Set NAS_HOME to the root of your NAS directory." 30 | exit(1) 31 | 32 | # Prepare state file for run 33 | if os.path.exists(stateFile): 34 | os.remove(stateFile) 35 | 36 | with Timer("Build"): 37 | #Change directory to NAS_HOME 38 | savedPath = os.getcwd() 39 | os.chdir(NAS_HOME) 40 | pcall(["rm -f {0}/*.o {0}/*.ll {0}/*.bc".format(args.benchmark.upper())]) 41 | returnCode = pcall(["make", args.benchmark, "CLASS={}".format(args.input), "CONFIG={}.def".format(args.config)], returnCode=True) 42 | os.chdir(savedPath) 43 | 44 | # Clean up 45 | if os.path.exists(stateFile): 46 | os.remove(stateFile) 47 | 48 | if returnCode != 0: 49 | util.print_error("Build failed") 50 | exit(1) 51 | 52 | 53 | if __name__ == "__main__": 54 | main() 55 | -------------------------------------------------------------------------------- /scripts/build_parsec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import argparse 5 | import subprocess 6 | import shutil 7 | from util import pcall, Timer 8 | import util 9 | 10 | def main(): 11 | parser = argparse.ArgumentParser(description="Builds a parsec benchmark with contech") 12 | parser.add_argument("benchmark", help="The parsec bencmark to build.") 13 | parser.add_argument("--bldconf", default="contech", help="PARSEC build configuration (bldconf) to use for building.") 14 | parser.add_argument("--hammerOptLevel", help="Set hammer optimization level (bldconf==hammer only)") 15 | args = parser.parse_args() 16 | 17 | if os.environ.has_key("CONTECH_HOME"): 18 | CONTECH_HOME = os.environ["CONTECH_HOME"] 19 | stateFile = os.path.join(CONTECH_HOME, "scripts/output/", args.benchmark + ".stateFile.temp") 20 | os.environ["CONTECH_STATE_FILE"] = stateFile 21 | else: 22 | print ">Error: Could not find contech installation. Set CONTECH_HOME to the root of your contech directory." 23 | exit(1) 24 | 25 | if os.environ.has_key("PARSEC_HOME"): 26 | PARSEC_HOME = os.environ["PARSEC_HOME"] 27 | PARSECMGMT = os.path.join(PARSEC_HOME, "bin/parsecmgmt") 28 | else: 29 | print ">Error: Could not find parsec installation. Set PARSEC_HOME to the root of your parsec directory." 30 | exit(1) 31 | 32 | 33 | # Run the parsec benchmark 34 | print ">Building " + args.benchmark 35 | 36 | # Prepare state file for run 37 | if os.path.exists(stateFile): 38 | os.remove(stateFile) 39 | 40 | # Hammer: Prepare hammer nail file 41 | if args.bldconf == "hammer": 42 | os.environ["HAMMER_NAIL_FILE"] = os.path.join(CONTECH_HOME, "backend/Hammer/compilerData/{}.bin".format(args.benchmark)) 43 | os.environ["HAMMER_OPT_LEVEL"] = args.hammerOptLevel 44 | 45 | pcall([PARSECMGMT, "-a", "uninstall", "-p", args.benchmark, "-c", args.bldconf]) 46 | with Timer("Build"): 47 | returnCode = pcall([PARSECMGMT, "-a", "build", "-p", args.benchmark, "-c", args.bldconf], returnCode=True) 48 | 49 | # Clean up 50 | if os.path.exists(stateFile): 51 | os.remove(stateFile) 52 | elif args.bldconf in ["contech", "contech_marker", "hammer"]: 53 | util.print_warning("Warning: no statefile was generated.") 54 | 55 | if returnCode != 0: 56 | util.print_error("Build failed") 57 | exit(1) 58 | 59 | 60 | if __name__ == "__main__": 61 | main() 62 | -------------------------------------------------------------------------------- /scripts/clear_cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo sh -c 'echo 1 >/proc/sys/vm/drop_caches' 4 | -------------------------------------------------------------------------------- /scripts/contech_marker++.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C marker compiler for contech front end 4 | 5 | import contech_wrapper 6 | 7 | contech_wrapper.main(isCpp = True, markOnly = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/contech_marker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C marker compiler for contech front end 4 | 5 | import contech_wrapper 6 | 7 | contech_wrapper.main(isCpp = False, markOnly = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/contech_wrapper++.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C++ Wrapper compiler for contech front end 4 | 5 | import contech_wrapper 6 | 7 | contech_wrapper.main(isCpp = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/contech_wrapper_minimal++.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C++ Wrapper compiler for contech front end 4 | 5 | import contech_wrapper 6 | 7 | contech_wrapper.main(isCpp = True, minimal = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/contech_wrapper_minimal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C++ Wrapper compiler for contech front end 4 | 5 | import contech_wrapper 6 | 7 | contech_wrapper.main(minimal = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/contech_wrapper_par++.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # C++ Wrapper compiler for contech front end 4 | 5 | import contech_wrapper_par 6 | 7 | contech_wrapper_par.main(isCpp = True) 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/mark_parsec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import argparse 5 | import subprocess 6 | import shutil 7 | from util import pcall 8 | import util 9 | 10 | def main(): 11 | CONTECH_HOME = util.findContechInstall() 12 | OBJPARSE = os.path.join(CONTECH_HOME, "scripts/objparse.py") 13 | 14 | PARSEC_HOME = util.findParsecInstall() 15 | PARSECMGMT = os.path.join(PARSEC_HOME, "bin/parsecmgmt") 16 | 17 | 18 | parser = argparse.ArgumentParser(description='Generates a marked object file (.mo) for a parsec benchmark') 19 | parser.add_argument('benchmark', help='The parsec benchmark.') 20 | args = parser.parse_args() 21 | 22 | stateFile = os.path.join(CONTECH_HOME, "scripts/output/", args.benchmark + ".stateFile.temp") 23 | os.environ["CONTECH_STATE_FILE"] = stateFile 24 | 25 | # Run the parsec benchmark 26 | print ">Building " + args.benchmark 27 | 28 | # Prepare state file for run 29 | if os.path.exists(stateFile): 30 | os.remove(stateFile) 31 | 32 | pcall([PARSECMGMT, "-a", "uninstall", "-p", args.benchmark, "-c", "contech_marker"]) 33 | pcall([PARSECMGMT, "-a", "build", "-p", args.benchmark, "-c", "contech_marker"]) 34 | 35 | # Find the executable generated by the build 36 | exe = os.path.join(PARSEC_HOME, "pkgs/apps/" + args.benchmark + "/inst/amd64-linux.contech_marker/bin/" + args.benchmark) 37 | # Parse the code to generate a marked object file 38 | markedObjectFile = os.path.join(CONTECH_HOME, "middle/output/" + args.benchmark + ".mo") 39 | pcall([OBJPARSE, exe, markedObjectFile]) 40 | 41 | # Clean up 42 | os.remove(stateFile) 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /scripts/output/.gitignore: -------------------------------------------------------------------------------- 1 | *.controlflowgraph 2 | *.temp 3 | -------------------------------------------------------------------------------- /scripts/overhead-scrape.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import json 13 | import math 14 | import csv 15 | import re 16 | 17 | def main(arg): 18 | if (len(arg)) == 1: 19 | print "Usage: {0} input\n".format(arg[0]) 20 | exit() 21 | 22 | p = 1 23 | for perf_in in arg[1:]: 24 | 25 | # try: 26 | with open(perf_in, "r") as csvfile: 27 | #sorry to use blah, but I blanked on a name for this latest temp 28 | blah = csv.reader(csvfile) 29 | i = 0 30 | bench = perf_in.split('/') 31 | perf_in = bench[-1] 32 | bench = perf_in.split('.') 33 | perf_in = bench[-2] 34 | totalBuffersQueued = 0 35 | totalCyclesQueued = 0 36 | totalCyclesNotQueued = 0 37 | start = 0.0 38 | end = 0.0 39 | for row in blah: 40 | # FIND CT_START and CT_END 41 | if (len(row) != 4): 42 | # Search for timestamps 43 | try: 44 | m = re.search(r"CT_(\w+): (\d+[.]\d+)", row[0]) 45 | if m: 46 | if m.group(1) == "START": 47 | start = float(m.group(2)) 48 | if m.group(1) == "END": 49 | end = float(m.group(2)) 50 | except IndexError: 51 | start = start 52 | continue 53 | try: 54 | if (row[0][0:2] != "T("): 55 | continue 56 | a = int(row[1]) 57 | b = int(row[2]) 58 | c = int(row[3]) 59 | totalCyclesQueued += a 60 | totalCyclesNotQueued += b 61 | totalBuffersQueued += c 62 | except IndexError: 63 | i = 0 64 | except ValueError: 65 | i = 0 66 | if (start == 0.0 or end == 0.0): 67 | continue 68 | if (totalCyclesQueued == 0): 69 | print "{}, {}".format(perf_in, end - start) 70 | else: 71 | print "{}, {}, {}, {}, {}".format(perf_in, end - start, totalCyclesQueued, totalCyclesNotQueued, totalBuffersQueued) 72 | #sys.stdout.write(perf_in) 73 | #sys.stdout.write("\n") 74 | 75 | if __name__ == "__main__": 76 | main(sys.argv) -------------------------------------------------------------------------------- /scripts/overhead.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import argparse 5 | import subprocess 6 | import shutil 7 | import util 8 | import glob 9 | 10 | def main(): 11 | CONTECH_HOME = util.findContechInstall() 12 | script = """ 13 | cd /net/tinker/brailing/contech/scripts 14 | 15 | ./build{3}.py {0} 16 | ./run{3}.py --traceOnly {0} -n 16 -i {2} --time "{1}" 17 | """ 18 | bset = util.Benchmarks.all 19 | time = "/usr/bin/time" 20 | for b in bset: 21 | util.quicksub(name="{}_{}".format(b, "perf"), code=script.format(b, time, "simmedium", "_parsec"), resources=["nodes=1:ppn=24"], queue="newpasta") 22 | for b in util.Benchmarks.nas: 23 | util.quicksub(name="{}_{}".format(b, "perf"), code=script.format(b, time, "A", "_nas"), resources=["nodes=1:ppn=24"], queue="newpasta") 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /scripts/perf-scrape.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | sys.path.append(os.path.join(os.environ["CONTECH_HOME"], "scripts")) 6 | import util 7 | import subprocess 8 | import shutil 9 | import time 10 | import datetime 11 | import glob 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.colors as colors 15 | import matplotlib as matplotlib 16 | import json 17 | import math 18 | import csv 19 | 20 | def main(arg): 21 | if (len(arg)) == 1: 22 | print "Usage: {0} input\n".format(arg[0]) 23 | exit() 24 | 25 | p = 1 26 | for perf_in in arg[1:]: 27 | 28 | # try: 29 | with open(perf_in, "r") as csvfile: 30 | #sorry to use blah, but I blanked on a name for this latest temp 31 | blah = csv.reader(csvfile) 32 | i = 0 33 | bench = perf_in.split('/') 34 | perf_in = bench[-1] 35 | bench = perf_in.split('.') 36 | perf_in = bench[-2] 37 | sys.stdout.write(perf_in) 38 | for row in blah: 39 | if (len(row) != 2): 40 | continue 41 | try: 42 | a = int(row[0]) 43 | if (i == 0): 44 | i = a 45 | else: 46 | v = float(a) / float(i) 47 | sys.stdout.write(", {}".format(v)) 48 | i = 0 49 | except IndexError: 50 | i = 0 51 | except ValueError: 52 | i = 0 53 | sys.stdout.write("\n") 54 | 55 | if __name__ == "__main__": 56 | main(sys.argv) -------------------------------------------------------------------------------- /scripts/perf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import argparse 5 | import subprocess 6 | import shutil 7 | import util 8 | import glob 9 | import time 10 | 11 | #/net/tinker/brailing/contech/benchmarks/parsec-3.0/bin/parsecmgmt -a run -p fluidanimate -c llvm -d /tmp/bpr -n 16 -i simmedium -s "perf stat -e L1-dcache-loads,L1-dcache-load-misses,L1-dcache-stores,L1-dcache-store-misses,branches,branch-misses,L1-icache-loads,L1-icache-load-misses,instructions,cycles /net/tinker/brailing/contech/../pin/pin-2.13-62732-gcc.4.4.7-linux/pin -t /net/tinker/brailing/contech/../pin/pin-2.13-62732-gcc.4.4.7-linux/source/tools/ManualExamples/obj-intel64/contech_fe.so --" 12 | 13 | def main(): 14 | CONTECH_HOME = util.findContechInstall() 15 | script = """ 16 | #!/bin/csh 17 | cd /net/tinker/brailing/contech/scripts 18 | 19 | ./build{3}.py {0} 20 | ./run{3}.py --traceOnly --discardTrace {0} -n 16 -i {2} --time "{1}" 21 | ./run{3}.py --traceOnly --discardTrace {0} -n 16 -i {2} --time "{1}" --pinFrontend 22 | {4} 23 | """ 24 | bset = util.Benchmarks.all 25 | timeCmd = "perf stat -x, -e L1-dcache-loads,L1-dcache-load-misses,L1-dcache-stores,L1-dcache-store-misses,branches,branch-misses,L1-icache-loads,L1-icache-load-misses,instructions,cycles" 26 | #timeCmd = "perf stat -x, -e LLC-loads,LLC-load-misses,LLC-stores,LLC-store-misses,bus-cycles,ref-cycles,stalled-cycles-frontend,stalled-cycles-backend" 27 | # for b in util.Benchmarks.nas: 28 | # util.quicksub(name="{}_{}".format(b, "perf"), code=script.format(b, timeCmd, "A", "_nas", nativeRunNas(b, 16, "A", time)), resources=["nodes=1:ppn=24,pmem=1gb"], queue="newpasta") 29 | # time.sleep(30) 30 | for b in bset: 31 | util.quicksub(name="{}_{}".format(b, "perf"), code=script.format(b, timeCmd, "simsmall", "_parsec",nativeRunParsec(b, 16, "simmedium", timeCmd)), resources=["nodes=1:ppn=24,pmem=1gb"], queue="newpasta") 32 | time.sleep(1) 33 | 34 | 35 | def nativeRunNas(benchmark, n, input, timeC): 36 | PARSEC_HOME = util.findParsecInstall() 37 | script = """ 38 | mkdir /tmp/$USER 39 | cp $NAS_HOME/bin-llvm/{0}.{2}.x /tmp/$USER 40 | cd /tmp/$USER 41 | setenv OMP_NUM_THREADS {1} 42 | {3} /tmp/$USER/{0}.{2}.x 43 | cd - 44 | rm -f /tmp/$USER/* 45 | """ 46 | script = script.format(benchmark, n, input, timeC) 47 | 48 | return script 49 | 50 | def nativeRunParsec(benchmark, n, input, timeC): 51 | 52 | PARSEC_HOME = util.findParsecInstall() 53 | script = """ 54 | mkdir /tmp/$USER 55 | $PARSEC_HOME/bin/parsecmgmt -a run -p {0} -c llvm -d /tmp/$USER -n {1} -i {2} -s "{3}" 56 | """ 57 | script = script.format(benchmark, n, input, timeC) 58 | 59 | return script 60 | 61 | if __name__ == "__main__": 62 | main() -------------------------------------------------------------------------------- /scripts/prepare_for_manifold.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import shutil 5 | from util import pcall 6 | import util 7 | import argparse 8 | 9 | def main(): 10 | CONTECH_HOME = util.findContechInstall() 11 | CONTECH_WRAPPER = os.path.join(CONTECH_HOME, "scripts/contech_wrapper.py") 12 | CONTECH_MARKER = os.path.join(CONTECH_HOME, "scripts/contech_marker.py") 13 | stateFile = os.path.join(CONTECH_HOME, "scripts/output/contechStateFile.temp") 14 | 15 | OBJPARSE = os.path.join(CONTECH_HOME, "scripts/objparse.py") 16 | RUN = os.path.join(CONTECH_HOME, "scripts/run.py") 17 | 18 | parser = argparse.ArgumentParser(description='Generates a task graph with a matching marked object file for a parsec benchmark') 19 | parser.add_argument('benchmark', help='The simple benchmark to build.') 20 | args = parser.parse_args() 21 | 22 | # Reset state file 23 | if os.path.exists(stateFile): 24 | os.remove(stateFile) 25 | 26 | # Marker run 27 | pcall([CONTECH_MARKER, args.benchmark + ".c", "-o", args.benchmark, "-lpthread", "-O3"]) 28 | 29 | # Objparse 30 | markedObjectFile = os.path.join(CONTECH_HOME, "middle/output/" + os.path.basename(args.benchmark) + ".mo") 31 | pcall([OBJPARSE, args.benchmark, markedObjectFile]) 32 | 33 | # Reset state file 34 | os.remove(stateFile) 35 | 36 | # Actual build 37 | pcall([CONTECH_WRAPPER, args.benchmark + ".c", "-o", args.benchmark, "-lpthread", "-O3"]) 38 | 39 | # Generate taskgraph 40 | pcall([RUN, args.benchmark]) 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /scripts/qscrape.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | import util 5 | import glob 6 | import json 7 | import argparse 8 | import scrape_build 9 | import scrape_run 10 | import aggregate_scrape_run 11 | 12 | def main(args): 13 | 14 | input = "qscrape" 15 | 16 | root = scrape_run.processAll(args[1:]) 17 | 18 | # Aggregate output 19 | table = aggregate_scrape_run.aggregate(root) 20 | aggregate_scrape_run.computeSlowdown(table) 21 | aggregate_scrape_run.generateRunCsv(table, "results-{}.csv".format(input)) 22 | 23 | 24 | if __name__ == "__main__": 25 | main(sys.argv) -------------------------------------------------------------------------------- /scripts/regress-local.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import util 4 | import glob 5 | import json 6 | import argparse 7 | import scrape_build 8 | import scrape_run 9 | import aggregate_scrape_run 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser(description= 13 | """Run a bunch of jobs to collect various statistics about contech. 14 | 1. Recompile all parsec benchmarks for bldconf's contech and llvm. 15 | 2. Run all parsec benchmarks using both bldconfs. 16 | 3. Run output aggregation scripts to collect the data and format into a table. 17 | """) 18 | parser.add_argument("-i", "--inputs", help="The input sets to run", default="simsmall simmedium simlarge") 19 | parser.add_argument("-n", "--numthreads", help="The number of threads to run.", default="8") 20 | parser.add_argument("-b", "--benchmarks", help="The benchmarks to run", default="") 21 | parser.add_argument("-r", "--run_only", help="Only run, do not compile", default=False, action='store_true') 22 | args = parser.parse_args() 23 | if args.benchmarks == "": 24 | args.benchmarks = util.Benchmarks.all 25 | else: 26 | args.benchmarks = args.benchmarks.split(" ") 27 | args.inputs = args.inputs.split(" ") 28 | 29 | regressContech(inputs=args.inputs, numthreads=args.numthreads, benchmarks=args.benchmarks, ro=args.run_only) 30 | 31 | def regressContech(inputs, numthreads, benchmarks, ro): 32 | 33 | # Rebuild benchmarks 34 | if ro == False: 35 | compileJobIds = [compilationTimeCompare(b) for b in benchmarks] 36 | buildRoot = scrape_build.processAll(compileJobIds) 37 | 38 | # Run the benchmarks 39 | os.environ["TIME"] = '{"real":%e, "user":%U, "sys":%S, "mem":%M }' 40 | for input in inputs: 41 | runJobIds = [] 42 | runJobIds.extend([statsRun(b, numthreads, input, "contech") for b in benchmarks]) 43 | runJobIds.extend([nativeRun(b, numthreads, input) for b in benchmarks]) 44 | root = buildRoot + scrape_run.processAll(runJobIds) 45 | 46 | # Aggregate output 47 | table = aggregate_scrape_run.aggregate(root) 48 | aggregate_scrape_run.computeSlowdown(table) 49 | aggregate_scrape_run.generateCsv(table, "results-{}.csv".format(input)) 50 | 51 | def compilationTimeCompare(benchmark): 52 | CONTECH_HOME = util.findContechInstall() 53 | script = """ 54 | cd $CONTECH_HOME/scripts 55 | """ 56 | 57 | test = """ 58 | # {0} 59 | ./build_parsec.py {0} --bldconf llvm | {1} 60 | ./build_parsec.py {0} --bldconf contech | {2} 61 | """ 62 | label = "sed s/'Build'/'{0}'/ " 63 | script += test.format(benchmark, label.format(benchmark+"-llvm"), label.format(benchmark+"-contech")) 64 | 65 | # print script 66 | return util.quicklocal(name="timed_compilation_{}".format(benchmark), code=script, resources=["nodes=1:ppn=1,pmem=1gb"], queue="newpasta") 67 | 68 | 69 | def nativeRun(benchmark, n, input): 70 | 71 | PARSEC_HOME = util.findParsecInstall() 72 | script = """ 73 | mkdir /tmp/$USER 74 | $PARSEC_HOME/bin/parsecmgmt -a run -p {0} -c llvm -d /tmp/$USER -n {1} -i {2} -s "/usr/bin/time" 75 | """ 76 | script = script.format(benchmark, n, input) 77 | jobName = "llvm_{}_{}_{}".format(input, n, benchmark) 78 | print jobName 79 | return util.quicklocal(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1800mb"], queue="newpasta") 80 | 81 | def statsRun(benchmark, n, input, option): 82 | 83 | CONTECH_HOME = util.findContechInstall() 84 | if os.environ.has_key("CONTECH_OUTDIR"): 85 | script = """ 86 | cd $CONTECH_HOME/scripts 87 | 88 | ./run_parsec.py {0} -n {1} -i {2} {3} --backends stats 89 | rm -f --verbose $CONTECH_OUTDIR/{0}.contech.trace 90 | rm -f --verbose $CONTECH_OUTDIR/{0}.taskgraph; 91 | """ 92 | else: 93 | script = """ 94 | cd $CONTECH_HOME/scripts 95 | 96 | ./run_parsec.py {0} -n {1} -i {2} {3} --backends stats 97 | rm -f --verbose /tmp/{0}.contech.trace 98 | rm -f --verbose /tmp/{0}.taskgraph; 99 | """ 100 | options = {"discard": "--discardTrace", 101 | "pin" : "--pinFrontend", 102 | "contech" : "", 103 | "contechmarker" : ""} 104 | 105 | script = script.format(benchmark, n, input, options[option]) 106 | jobName = "{}_{}_{}_{}".format(option, input, n, benchmark) 107 | print jobName 108 | return util.quicklocal(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1800mb"], queue="newpasta") 109 | 110 | 111 | if __name__ == "__main__": 112 | main() 113 | -------------------------------------------------------------------------------- /scripts/regress-nas.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import util 4 | import glob 5 | import json 6 | import argparse 7 | import scrape_build 8 | import scrape_run 9 | import aggregate_scrape_run 10 | import time 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser(description= 14 | """Run a bunch of jobs to collect various statistics about contech. 15 | 1. Recompile all parsec benchmarks for bldconf's contech and llvm. 16 | 2. Run all parsec benchmarks using both bldconfs. 17 | 3. Run output aggregation scripts to collect the data and format into a table. 18 | """) 19 | parser.add_argument("-i", "--inputs", help="The input sets to run", default="S W A") 20 | parser.add_argument("-n", "--numthreads", help="The number of threads to run.", default="16") 21 | parser.add_argument("-b", "--benchmarks", help="The benchmarks to run", default="") 22 | args = parser.parse_args() 23 | if args.benchmarks == "": 24 | args.benchmarks = util.Benchmarks.nas 25 | else: 26 | args.benchmarks = args.benchmarks.split(" ") 27 | args.inputs = args.inputs.split(" ") 28 | 29 | regressContech(inputs=args.inputs, numthreads=args.numthreads, benchmarks=args.benchmarks) 30 | 31 | def regressContech(inputs, numthreads, benchmarks): 32 | 33 | if os.environ.has_key("NAS_HOME"): 34 | NAS_HOME = os.environ["NAS_HOME"] 35 | else: 36 | print ">Error: Could not find NAS installation. Set NAS_HOME to the root of your NAS directory." 37 | exit(1) 38 | 39 | # Rebuild benchmarks 40 | # NAS must be built sequentially 41 | compileJobIds = [] 42 | for input in inputs: 43 | for b in benchmarks: 44 | x = compilationTimeCompare(b, input) 45 | compileJobIds.append(x) 46 | util.waitForJobs(x) 47 | time.sleep(10) #Wait for files to be copied back 48 | buildRoot = scrape_build.processAll([util.getFileNameForJob(j) for j in compileJobIds]) 49 | 50 | # Run the benchmarks 51 | os.environ["TIME"] = '{"real":%e, "user":%U, "sys":%S, "mem":%M }' 52 | for input in inputs: 53 | runJobIds = [] 54 | runJobIds.extend([statsRun(b, numthreads, input, "contech") for b in benchmarks]) 55 | runJobIds.extend([nativeRun(b, numthreads, input) for b in benchmarks]) 56 | util.waitForJobs(runJobIds) 57 | root = buildRoot + scrape_run.processAll([util.getFileNameForJob(j) for j in runJobIds]) 58 | 59 | # Aggregate output 60 | table = aggregate_scrape_run.aggregate(root) 61 | aggregate_scrape_run.computeSlowdown(table) 62 | aggregate_scrape_run.generateCsv(table, "results-{}.csv".format(input)) 63 | 64 | def compilationTimeCompare(benchmark, input): 65 | CONTECH_HOME = util.findContechInstall() 66 | script = """ 67 | cd $CONTECH_HOME/scripts 68 | """ 69 | 70 | test = """ 71 | # {0} 72 | ./build_nas.py {0} -i {3} -c llvm | {1} 73 | ./build_nas.py {0} -i {3} -c contech | {2} 74 | """ 75 | label = "sed s/'Build'/'{0}'/ " 76 | script += test.format(benchmark, label.format(benchmark+"-llvm"), label.format(benchmark+"-contech"), input) 77 | 78 | # print script 79 | return util.quicksub(name="timed_compilation_{}".format(benchmark), code=script, resources=["nodes=1:ppn=1,pmem=1gb"], queue="newpasta") 80 | 81 | def nativeRun(benchmark, n, input): 82 | PARSEC_HOME = util.findParsecInstall() 83 | script = """ 84 | mkdir /tmp/$USER 85 | cp $NAS_HOME/bin-llvm/{0}.{2}.x /tmp/$USER 86 | cd /tmp/$USER 87 | setenv OMP_NUM_THREADS {1} 88 | /usr/bin/time /tmp/$USER/{0}.{2}.x 89 | cd - 90 | rm -f /tmp/$USER/* 91 | """ 92 | script = script.format(benchmark, n, input) 93 | jobName = "llvm_{}_{}_{}".format(input, n, benchmark) 94 | print jobName 95 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1gb"], queue="newpasta") 96 | 97 | def statsRun(benchmark, n, input, option): 98 | 99 | CONTECH_HOME = util.findContechInstall() 100 | if os.environ.has_key("CONTECH_OUTDIR"): 101 | script = """ 102 | cd $CONTECH_HOME/scripts 103 | 104 | ./run_nas.py {0} -n {1} -i {2} {3} --backends stats 105 | rm -f --verbose $CONTECH_OUTDIR/{0}.contech.trace 106 | rm -f --verbose $CONTECH_OUTDIR/{0}.taskgraph; 107 | """ 108 | else: 109 | script = """ 110 | cd $CONTECH_HOME/scripts 111 | 112 | ./run_nas.py {0} -n {1} -i {2} {3} --backends stats 113 | rm -f --verbose /tmp/{0}.contech.trace 114 | rm -f --verbose /tmp/{0}.taskgraph; 115 | """ 116 | options = {"discard": "--discardTrace", 117 | "pin" : "--pinFrontend", 118 | "contech" : "", 119 | "contechmarker" : ""} 120 | 121 | script = script.format(benchmark, n, input, options[option]) 122 | jobName = "{}_{}_{}_{}".format(option, input, n, benchmark) 123 | print jobName 124 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1gb"], queue="newpasta") 125 | 126 | 127 | if __name__ == "__main__": 128 | main() 129 | -------------------------------------------------------------------------------- /scripts/regress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import util 4 | import glob 5 | import json 6 | import argparse 7 | import scrape_build 8 | import scrape_run 9 | import aggregate_scrape_run 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser(description= 13 | """Run a bunch of jobs to collect various statistics about contech. 14 | 1. Recompile all parsec benchmarks for bldconf's contech and llvm. 15 | 2. Run all parsec benchmarks using both bldconfs. 16 | 3. Run output aggregation scripts to collect the data and format into a table. 17 | """) 18 | parser.add_argument("-i", "--inputs", help="The input sets to run", default="simsmall simmedium simlarge") 19 | parser.add_argument("-n", "--numthreads", help="The number of threads to run.", default="16") 20 | parser.add_argument("-b", "--benchmarks", help="The benchmarks to run", default="") 21 | parser.add_argument("-r", "--run_only", help="Only run, do not compile", default=False, action='store_true') 22 | args = parser.parse_args() 23 | if args.benchmarks == "": 24 | args.benchmarks = util.Benchmarks.all 25 | else: 26 | args.benchmarks = args.benchmarks.split(" ") 27 | args.inputs = args.inputs.split(" ") 28 | 29 | regressContech(inputs=args.inputs, numthreads=args.numthreads, benchmarks=args.benchmarks, ro=args.run_only) 30 | 31 | def regressContech(inputs, numthreads, benchmarks, ro): 32 | 33 | # Rebuild benchmarks 34 | if ro == False: 35 | compileJobIds = [compilationTimeCompare(b) for b in benchmarks] 36 | util.waitForJobs(compileJobIds) 37 | buildRoot = scrape_build.processAll([util.getFileNameForJob(j) for j in compileJobIds]) 38 | 39 | # Run the benchmarks 40 | os.environ["TIME"] = '{"real":%e, "user":%U, "sys":%S, "mem":%M }' 41 | for input in inputs: 42 | runJobIds = [] 43 | runJobIds.extend([statsRun(b, numthreads, input, "contech") for b in benchmarks]) 44 | runJobIds.extend([nativeRun(b, numthreads, input) for b in benchmarks]) 45 | util.waitForJobs(runJobIds) 46 | root = buildRoot + scrape_run.processAll([util.getFileNameForJob(j) for j in runJobIds]) 47 | 48 | # Aggregate output 49 | table = aggregate_scrape_run.aggregate(root) 50 | aggregate_scrape_run.computeSlowdown(table) 51 | aggregate_scrape_run.generateCsv(table, "results-{}.csv".format(input)) 52 | 53 | def compilationTimeCompare(benchmark): 54 | CONTECH_HOME = util.findContechInstall() 55 | script = """ 56 | cd $CONTECH_HOME/scripts 57 | """ 58 | 59 | test = """ 60 | # {0} 61 | ./build_parsec.py {0} --bldconf llvm | {1} 62 | ./build_parsec.py {0} --bldconf contech | {2} 63 | """ 64 | label = "sed s/'Build'/'{0}'/ " 65 | script += test.format(benchmark, label.format(benchmark+"-llvm"), label.format(benchmark+"-contech")) 66 | 67 | # print script 68 | return util.quicksub(name="timed_compilation_{}".format(benchmark), code=script, resources=["nodes=1:ppn=1,pmem=1gb"], queue="newpasta") 69 | 70 | def nativeRun(benchmark, n, input): 71 | 72 | PARSEC_HOME = util.findParsecInstall() 73 | script = """ 74 | mkdir /tmp/$USER 75 | $PARSEC_HOME/bin/parsecmgmt -a run -p {0} -c llvm -d /tmp/$USER -n {1} -i {2} -s "/usr/bin/time" 76 | """ 77 | script = script.format(benchmark, n, input) 78 | jobName = "llvm_{}_{}_{}".format(input, n, benchmark) 79 | print jobName 80 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1800mb"], queue="newpasta") 81 | 82 | def statsRun(benchmark, n, input, option): 83 | 84 | CONTECH_HOME = util.findContechInstall() 85 | if os.environ.has_key("CONTECH_OUTDIR"): 86 | script = """ 87 | cd $CONTECH_HOME/scripts 88 | 89 | ./run_parsec.py {0} -n {1} -i {2} {3} --backends stats 90 | rm -f --verbose $CONTECH_OUTDIR/{0}.contech.trace 91 | rm -f --verbose $CONTECH_OUTDIR/{0}.taskgraph; 92 | """ 93 | else: 94 | script = """ 95 | cd $CONTECH_HOME/scripts 96 | 97 | ./run_parsec.py {0} -n {1} -i {2} {3} --backends stats 98 | rm -f --verbose /tmp/{0}.contech.trace 99 | rm -f --verbose /tmp/{0}.taskgraph; 100 | """ 101 | options = {"discard": "--discardTrace", 102 | "pin" : "--pinFrontend", 103 | "contech" : "", 104 | "contechmarker" : ""} 105 | 106 | script = script.format(benchmark, n, input, options[option]) 107 | jobName = "{}_{}_{}_{}".format(option, input, n, benchmark) 108 | print jobName 109 | return util.quicksub(name=jobName, code=script, resources=["nodes=1:ppn=24,pmem=1800mb"], queue="newpasta") 110 | 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /scripts/run_nas.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import run 4 | 5 | run.main(nas=True) 6 | 7 | -------------------------------------------------------------------------------- /scripts/run_parsec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import run 4 | 5 | run.main(parsec=True) 6 | -------------------------------------------------------------------------------- /scripts/run_rodinia.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import run 4 | 5 | run.main(rodinia=True) 6 | -------------------------------------------------------------------------------- /scripts/scrape_build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import re 6 | import json 7 | import fileinput 8 | 9 | def main(): 10 | print json.dumps(processAll(sys.argv[1:])) 11 | 12 | def processAll(filenames): 13 | root = [] 14 | for file in filenames: 15 | root.extend(process(file)) 16 | return root 17 | 18 | def process(filename): 19 | results = [] 20 | with open(filename) as file: 21 | for line in file: 22 | 23 | # Remove color codes 24 | line = re.sub("\033\[[0-9;]+m", "", line) 25 | 26 | m = re.search(r"(\w+)-(\w+) finished in (\d+[.]\d+) seconds", line) 27 | if m: 28 | row = dict() 29 | row["name"] = m.group(1) 30 | config = m.group(2) 31 | time = m.group(3) 32 | row[config + "BuildTime"] = time 33 | results.append(row) 34 | m = re.search(r"(\w+)-(\w+) failed", line) 35 | if m: 36 | row = dict() 37 | row["name"] = m.group(1) 38 | config = m.group(2) 39 | row[config + "BuildTime"] = "FAILED" 40 | results.append(row) 41 | 42 | return results 43 | 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | -------------------------------------------------------------------------------- /scripts/scrape_run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import re 6 | import json 7 | 8 | def main(): 9 | print json.dumps(processAll(sys.argv[1:])) 10 | 11 | def processAll(filenames): 12 | runs = [] 13 | for file in filenames: 14 | m = re.match("(\w+)_(\w+)_(\w+)_([\w.]+).o\d{5}", file) 15 | root = dict() 16 | if m: 17 | root["config"] = m.group(1) 18 | root["input"] = m.group(2) 19 | root["nThreads"] = m.group(3) 20 | root["name"] = m.group(4) 21 | runs.append(process(file, root)) 22 | return runs 23 | 24 | def process(filename, root): 25 | 26 | with open(filename) as file: 27 | for line in file: 28 | 29 | # Remove color codes 30 | line = re.sub("\033\[[0-9;]+m", "", line) 31 | 32 | # Parse stats output 33 | if "stats" in root: 34 | if ":" in line: 35 | key, value = tuple(line.split(":")) 36 | root["stats"][key.strip()] = value.strip() 37 | elif "stats finished in" in line: # End of output, next file 38 | break 39 | else: 40 | 41 | # Search for timestamps 42 | m = re.search(r"CT_(\w+): (\d+[.]\d+)", line) 43 | if m: 44 | if "timestamps" not in root: root["timestamps"] = dict() 45 | root["timestamps"][m.group(1)] = m.group(2) 46 | 47 | # Search for uncompressed bytes written 48 | m = re.search(r"Total Uncomp Written: (\d+)", line) 49 | if m: 50 | root["uncompressedBytes"] = int(m.group(1)) 51 | 52 | # Search for execution time 53 | if '{"real"' in line: 54 | root["executionTime"] = json.loads(line) 55 | 56 | # Search for middle layer time 57 | m = re.search(r"Middle layer finished in (\d+[.]\d+)", line) 58 | if m: 59 | root["middleTime"] = m.group(1) 60 | 61 | # Beginning of stats output 62 | if "Statistics for" in line: 63 | root["stats"] = dict() 64 | 65 | # Compute duration 66 | if "timestamps" in root: 67 | t = root["timestamps"] 68 | if "END" in t and "START" in t and "COMP" in t: 69 | t["RUNTIME"] = float(t["END"]) - float(t["START"]) 70 | t["FLUSHTIME"] = float(t["COMP"]) - float(t["END"]) 71 | t["TOTAL"] = float(t["COMP"]) - float(t["START"]) 72 | 73 | return root 74 | 75 | if __name__ == "__main__": 76 | main() 77 | -------------------------------------------------------------------------------- /scripts/uniq_ar_x.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | path=`pwd` 4 | archive=$1 5 | tmp=`mktemp -d` 6 | cd $tmp 7 | mkdir ofiles 8 | cp $path/$archive . 9 | master_count=`ar t $archive | wc -w` 10 | #echo master_count=$master_count 11 | ar t $archive | xargs -n1 > master_list 12 | #echo master_list: ` cat master_list` 13 | count=0 14 | subdir=1 15 | comm_list='' 16 | for files in `cat master_list | sort | uniq` 17 | do 18 | n=`grep -w $files master_list | wc -l` 19 | if [ "$n" -gt 1 ] 20 | then 21 | #echo $files: $n 22 | for i in ` seq 1 $n` 23 | do 24 | comm_list=`echo $comm_list $files` 25 | done 26 | fi 27 | done 28 | #echo Repeated files: $comm_list 29 | #echo Extracting blindly 30 | ar x $archive 31 | count=`ls *.o | wc -w` 32 | #echo count=$count 33 | mv *.o ofiles/ 34 | until [ "$master_count" == "$count" ] 35 | do 36 | list=`echo $comm_list | xargs -n1 | sort | uniq` 37 | for files in $list 38 | do 39 | comm_list=`echo $comm_list | sed "s/$files//"` 40 | done 41 | if [ "$comm_list" != "" ] 42 | then 43 | #echo Pushing $comm_list to end of $archive to expose new ones 44 | ar m $archive $comm_list 45 | #echo Extracting $comm_list from $archive 46 | ar x $archive $comm_list 47 | #echo Creating archive with extracted $comm_list 48 | ar rcs ${archive}_${subdir} $comm_list 49 | ar t ${archive}_${subdir} | xargs -n1 > subdir_list 50 | #echo ${subdir}_list: `cat subdir_list` 51 | #comm_list=`grep -Fwf master_list subdir_list` 52 | subdir_count=`echo $comm_list | xargs -n1 | sort | uniq | wc -l` 53 | count=`echo $subdir_count + $count | bc -l` 54 | #echo count: $count 55 | subdir=`echo $subdir + 1 | bc -l` 56 | rename .o .$subdir.o *.o 57 | mv *.o ofiles/ 58 | else 59 | break 60 | fi 61 | done 62 | cd $path 63 | mv $tmp/ofiles/*.o . 64 | rm -rf $tmp 65 | 66 | --------------------------------------------------------------------------------