centralized performance resources

This commit is contained in:
Barrett Ruth 2026-01-10 12:21:52 -05:00
commit 50b15a1522
63 changed files with 328466 additions and 0 deletions

BIN
ocw/1/assignment.pdf Normal file

Binary file not shown.

31
ocw/1/c-primer/Makefile Normal file
View file

@ -0,0 +1,31 @@
CC := clang
ifeq ($(DEBUG),1)
CFLAGS := -Wall -O0 -g
else
CFLAGS := -Wall -O1 -DNDEBUG
endif
LDFLAGS := -lrt -flto -fuse-ld=gold
all: sizes pointer swap
sizes.o: sizes.c
$(CC) $(CFLAGS) -c sizes.c
sizes: sizes.o
$(CC) -o sizes sizes.o $(LDFLAGS)
pointer.o: pointer.c
$(CC) $(CFLAGS) -c pointer.c
pointer: pointer.o
$(CC) -o pointer pointer.o $(LDFLAGS)
swap.o: swap.c
$(CC) $(CFLAGS) -c swap.c
swap: swap.o
$(CC) -o swap swap.o $(LDFLAGS)
clean:
rm -f sizes pointer swap *.o *.gcda *.gcno *.gcov perf.data */perf.data cachegrind.out.*

47
ocw/1/c-primer/pointer.c Normal file
View file

@ -0,0 +1,47 @@
// Copyright (c) 2012 MIT License by 6.172 Staff
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char * argv[]) { // What is the type of argv?
int i = 5;
// The & operator here gets the address of i and stores it into pi
int * pi = &i;
// The * operator here dereferences pi and stores the value -- 5 --
// into j.
int j = *pi;
char c[] = "6.172";
char * pc = c; // Valid assignment: c acts like a pointer to c[0] here.
char d = *pc;
printf("char d = %c\n", d); // What does this print?
// compound types are read right to left in C.
// pcp is a pointer to a pointer to a char, meaning that
// pcp stores the address of a char pointer.
char ** pcp;
pcp = argv; // Why is this assignment valid?
const char * pcc = c; // pcc is a pointer to char constant
char const * pcc2 = c; // What is the type of pcc2?
// For each of the following, why is the assignment:
*pcc = '7'; // invalid?
pcc = *pcp; // valid?
pcc = argv[0]; // valid?
char * const cp = c; // cp is a const pointer to char
// For each of the following, why is the assignment:
cp = *pcp; // invalid?
cp = *argv; // invalid?
*cp = '!'; // valid?
const char * const cpc = c; // cpc is a const pointer to char const
// For each of the following, why is the assignment:
cpc = *pcp; // invalid?
cpc = argv[0]; // invalid?
*cpc = '@'; // invalid?
return 0;
}

View file

@ -0,0 +1,21 @@
// Copyright (c) 2012 MIT License by 6.172 Staff
// All occurences of ONE will be replaced by 1.
#define ONE 1
// Macros can also behave similar to inline functions.
// Note that parentheses around arguments are required to preserve order of
// operations. Otherwise, you can introduce bugs when substitution happens
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int c = ONE, d = ONE + 5;
int e = MIN(c, d);
#ifndef NDEBUG
// This code will be compiled only when
// the macro NDEBUG is not defined.
// Recall that if clang is passed -DNDEBUG on the command line,
// then NDEBUG will be defined.
if (something) {}
#endif

14
ocw/1/c-primer/sizes.c Normal file
View file

@ -0,0 +1,14 @@
// Copyright (c) 2012 MIT License by 6.172 Staff
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void subprocedure(int x, int y) {
int z = x + y;
}
int main() {
int x = 3, y = 5;
subprocedure(x, y);
}

476
ocw/1/c-primer/sizes.s Normal file
View file

@ -0,0 +1,476 @@
.file "sizes.c"
.text
.Ltext0:
.file 0 "/home/frozen/dev/performance-engineering-ocw/1/c-primer" "sizes.c"
.section .rodata
.LC0:
.string "size of int : %zu bytes \n"
.LC1:
.string "size of you : %zu bytes \n"
.text
.globl main
.type main, @function
main:
.LFB6:
.file 1 "sizes.c"
.loc 1 9 12
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $48, %rsp
.loc 1 9 12
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
.loc 1 18 3
leaq .LC0(%rip), %rax
movl $4, %esi
movq %rax, %rdi
movl $0, %eax
call printf@PLT
.loc 1 35 10
movl $12345, -40(%rbp)
.loc 1 36 12
movl $4, -36(%rbp)
.loc 1 43 3
leaq .LC1(%rip), %rax
movl $8, %esi
movq %rax, %rdi
movl $0, %eax
call printf@PLT
.loc 1 45 10
movl $0, %eax
.loc 1 46 1
movq -8(%rbp), %rdx
subq %fs:40, %rdx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size main, .-main
.Letext0:
.file 2 "/usr/include/stdio.h"
.section .debug_info,"",@progbits
.Ldebug_info0:
.long 0x118
.value 0x5
.byte 0x1
.byte 0x8
.long .Ldebug_abbrev0
.uleb128 0x3
.long .LASF13
.byte 0x1d
.byte 0x3
.long 0x31647
.long .LASF0
.long .LASF1
.quad .Ltext0
.quad .Letext0-.Ltext0
.long .Ldebug_line0
.uleb128 0x1
.byte 0x8
.byte 0x7
.long .LASF2
.uleb128 0x1
.byte 0x4
.byte 0x7
.long .LASF3
.uleb128 0x1
.byte 0x1
.byte 0x8
.long .LASF4
.uleb128 0x1
.byte 0x2
.byte 0x7
.long .LASF5
.uleb128 0x1
.byte 0x1
.byte 0x6
.long .LASF6
.uleb128 0x1
.byte 0x2
.byte 0x5
.long .LASF7
.uleb128 0x4
.byte 0x4
.byte 0x5
.string "int"
.uleb128 0x1
.byte 0x8
.byte 0x5
.long .LASF8
.uleb128 0x1
.byte 0x1
.byte 0x6
.long .LASF9
.uleb128 0x5
.long 0x6b
.uleb128 0x6
.byte 0x8
.long 0x72
.uleb128 0x1
.byte 0x8
.byte 0x5
.long .LASF10
.uleb128 0x1
.byte 0x8
.byte 0x7
.long .LASF11
.uleb128 0x7
.long .LASF14
.byte 0x2
.value 0x16b
.byte 0xc
.long 0x5d
.long 0xa3
.uleb128 0x8
.long 0x77
.uleb128 0x9
.byte 0
.uleb128 0xa
.long .LASF15
.byte 0x1
.byte 0x9
.byte 0x5
.long 0x5d
.quad .LFB6
.quad .LFE6-.LFB6
.uleb128 0x1
.byte 0x9c
.long 0x10f
.uleb128 0xb
.byte 0x8
.byte 0x1
.byte 0x1d
.byte 0xb
.long 0xe8
.uleb128 0xc
.string "id"
.byte 0x1
.byte 0x1e
.byte 0x9
.long 0x5d
.byte 0
.uleb128 0xd
.long .LASF12
.byte 0x1
.byte 0x1f
.byte 0x9
.long 0x5d
.byte 0x4
.byte 0
.uleb128 0xe
.long .LASF16
.byte 0x1
.byte 0x20
.byte 0x5
.long 0xc5
.uleb128 0x2
.string "you"
.byte 0x22
.byte 0xb
.long 0xe8
.uleb128 0x2
.byte 0x91
.sleb128 -56
.uleb128 0x2
.string "x"
.byte 0x28
.byte 0x7
.long 0x10f
.uleb128 0x2
.byte 0x91
.sleb128 -48
.byte 0
.uleb128 0xf
.long 0x5d
.uleb128 0x10
.long 0x33
.byte 0x4
.byte 0
.byte 0
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.uleb128 0x1
.uleb128 0x24
.byte 0
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.uleb128 0x3
.uleb128 0xe
.byte 0
.byte 0
.uleb128 0x2
.uleb128 0x34
.byte 0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0x21
.sleb128 1
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0x18
.byte 0
.byte 0
.uleb128 0x3
.uleb128 0x11
.byte 0x1
.uleb128 0x25
.uleb128 0xe
.uleb128 0x13
.uleb128 0xb
.uleb128 0x90
.uleb128 0xb
.uleb128 0x91
.uleb128 0x6
.uleb128 0x3
.uleb128 0x1f
.uleb128 0x1b
.uleb128 0x1f
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x7
.uleb128 0x10
.uleb128 0x17
.byte 0
.byte 0
.uleb128 0x4
.uleb128 0x24
.byte 0
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.uleb128 0x3
.uleb128 0x8
.byte 0
.byte 0
.uleb128 0x5
.uleb128 0x26
.byte 0
.uleb128 0x49
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x6
.uleb128 0xf
.byte 0
.uleb128 0xb
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x7
.uleb128 0x2e
.byte 0x1
.uleb128 0x3f
.uleb128 0x19
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0x5
.uleb128 0x39
.uleb128 0xb
.uleb128 0x27
.uleb128 0x19
.uleb128 0x49
.uleb128 0x13
.uleb128 0x3c
.uleb128 0x19
.uleb128 0x1
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x8
.uleb128 0x5
.byte 0
.uleb128 0x49
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x9
.uleb128 0x18
.byte 0
.byte 0
.byte 0
.uleb128 0xa
.uleb128 0x2e
.byte 0x1
.uleb128 0x3f
.uleb128 0x19
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x27
.uleb128 0x19
.uleb128 0x49
.uleb128 0x13
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x7
.uleb128 0x40
.uleb128 0x18
.uleb128 0x7c
.uleb128 0x19
.uleb128 0x1
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0xb
.uleb128 0x13
.byte 0x1
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x1
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0xc
.uleb128 0xd
.byte 0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x38
.uleb128 0xb
.byte 0
.byte 0
.uleb128 0xd
.uleb128 0xd
.byte 0
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x38
.uleb128 0xb
.byte 0
.byte 0
.uleb128 0xe
.uleb128 0x16
.byte 0
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x39
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0xf
.uleb128 0x1
.byte 0x1
.uleb128 0x49
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x10
.uleb128 0x21
.byte 0
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2f
.uleb128 0xb
.byte 0
.byte 0
.byte 0
.section .debug_aranges,"",@progbits
.long 0x2c
.value 0x2
.long .Ldebug_info0
.byte 0x8
.byte 0
.value 0
.value 0
.quad .Ltext0
.quad .Letext0-.Ltext0
.quad 0
.quad 0
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.LASF10:
.string "long long int"
.LASF3:
.string "unsigned int"
.LASF15:
.string "main"
.LASF13:
.string "GNU C23 15.1.1 20250425 -mtune=generic -march=x86-64 -g -O0"
.LASF2:
.string "long unsigned int"
.LASF11:
.string "long long unsigned int"
.LASF4:
.string "unsigned char"
.LASF9:
.string "char"
.LASF8:
.string "long int"
.LASF16:
.string "student"
.LASF12:
.string "year"
.LASF5:
.string "short unsigned int"
.LASF14:
.string "printf"
.LASF7:
.string "short int"
.LASF6:
.string "signed char"
.section .debug_line_str,"MS",@progbits,1
.LASF0:
.string "sizes.c"
.LASF1:
.string "/home/frozen/dev/performance-engineering-ocw/1/c-primer"
.ident "GCC: (GNU) 15.1.1 20250425"
.section .note.GNU-stack,"",@progbits

21
ocw/1/c-primer/swap.c Normal file
View file

@ -0,0 +1,21 @@
// Copyright (c) 2012 MIT License by 6.172 Staff
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void swap(int i, int j) {
int temp = i;
i = j;
j = temp;
}
int main() {
int k = 1;
int m = 2;
swap(k, m);
// What does this print?
printf("k = %d, m = %d\n", k, m);
return 0;
}

111
ocw/1/c-primer/verifier.py Normal file
View file

@ -0,0 +1,111 @@
#!/usr/bin/python
import subprocess, os, sys, re
def exitWithError(error):
print error
sys.exit(1)
def runAndReadOutput(args):
if args is str:
args = [args]
try:
return subprocess.check_output(args)
except subprocess.CalledProcessError as e:
exitWithError("ERROR: runtime error with %s" % str(args))
def run(path): runAndReadOutput(path)
def runAndCheckSizes():
output = runAndReadOutput("./sizes")
expected_output_format = "size of %s : %d bytes"
lines = set([x.replace(" ", "") for x in output.strip().lower().split('\n')])
types = [
( "int", 4 ),
( "short", 2 ),
( "long", 8 ),
( "char", 1 ),
( "float", 4 ),
( "double", 8 ),
( "unsigned int", 4 ),
( "long long", 8 ),
( "uint8_t", 1 ),
( "uint16_t", 2 ),
( "uint32_t", 4 ),
( "uint64_t", 8 ),
( "uint_fast8_t", 1 ),
( "uint_fast16_t", 8 ),
( "uintmax_t", 8 ),
( "intmax_t", 8 ),
( "__int128", 16 ),
( "uint32_t", 4 ),
( "uint64_t", 8 ),
( "student", 8 ),
( "x", 20),
( "int*", 8 ),
( "short*", 8 ),
( "long*", 8 ),
( "char*", 8 ),
( "float*", 8 ),
( "double*", 8 ),
( "unsigned int*", 8 ),
( "long long*", 8 ),
( "uint8_t*", 8 ),
( "uint16_t*", 8 ),
( "uint32_t*", 8 ),
( "uint64_t*", 8 ),
( "uint_fast8_t*", 8 ),
( "uint_fast16_t*", 8 ),
( "uintmax_t*", 8 ),
( "intmax_t*", 8 ),
( "__int128*", 8 ),
( "uint32_t*", 8 ),
( "uint64_t*", 8 ),
( "student*", 8 ),
( "&x", 8)
]
for typ in types:
print (expected_output_format % typ)
if (expected_output_format % typ).replace(" ", "") not in lines:
exitWithError("ERROR: couldn't find type %s (or it has the incorrect value) in sizes output" % typ[0])
def runAndCheckSwap():
expected_output = "k = 2, m = 1\n"
output = runAndReadOutput("./swap")
if output != expected_output:
exitWithError('ERROR: actual output: "%s", expected "%s"' % (output, expected_output))
def build(make_arg, filename):
print "\nRunning make %s ... " % make_arg
run(["make", filename])
print "Ok!"
print "\nChecking that %s was built ... " % filename
if not os.path.isfile(filename):
exitWithError("ERROR: %s binary missing, did you rename it?" % filename)
print "Ok!"
print "Running verifying script ... "
print "\nChecking that the Makefile exists ... "
if not os.path.isfile('Makefile'):
exitWithError('ERROR: Makefile does not exist.')
print "Good!"
build("sizes", "sizes")
print "Checking output of sizes ... "
runAndCheckSizes()
print "Ok!"
build("pointer", "pointer")
run("./pointer") # Run pointer as a sanity check, but there's no output to check
build("swap", "swap")
print "Checking output of swap ... "
runAndCheckSwap()
print "Ok!"
print "LGTM"

View file

@ -0,0 +1,105 @@
# Copyright (c) 2012 MIT License by 6.172 Staff
# List all of your source files here (but not your headers), separated by
# spaces. You'll have to add to this list every time you create a new
# source file.
SRC := testbed.c matrix_multiply.c
# Set the name of your binary. Change it if you like.
PRODUCT := matrix_multiply
################################################################################
# These configuration options change how your code (listed above) is compiled
# every time you type "make". You may have to change these values to complete
# some assignments; you should also feel free to experiment with them.
################################################################################
# This option sets which compiler your code will be compiled with. Likely
# choices are icc, icpc, gcc, g++, clang
CC := clang
# These flags will be applied to your code any time it is built.
CFLAGS := -Wall -std=c99 -D_POSIX_C_SOURCE=200809L -O3
# These flags are applied only if you build your code with "make DEBUG=1". -g
# generates debugging symbols, -DDEBUG defines the preprocessor symbol "DEBUG"
# (so that you can use "#ifdef DEBUG" in your code), and -O0 disables compiler
# optimizations, so that the binary generated more directly corresponds to your
# source code.
CFLAGS_DEBUG := -g -DDEBUG -O0
# In the release version, we ask for many optimizations; -O3 sets the
# optimization level to three. -DNDEBUG defines the NDEBUG macro,
# which disables assertion checks.
CFLAGS_RELEASE := -O1 -DNDEBUG
# These flags are used to invoke Clang's address sanitizer.
CFLAGS_ASAN := -O1 -g -fsanitize=address
# These flags are applied when linking object files together into your binary.
# If you need to link against libraries, add the appropriate flags here. By
# default, your code is linked against the "rt" library with the flag -lrt;
# this library is used by the timing code in the testbed.
LDFLAGS := -lrt -flto -fuse-ld=gold
################################################################################
# You probably won't need to change anything below this line, but if you're
# curious about how makefiles work, or if you'd like to customize the behavior
# of your makefile, go ahead and take a peek.
################################################################################
# You shouldn't need to touch this. This keeps track of whether you are
# building in a release or debug configuration, and sets CFLAGS appropriately.
# (This mechanism is based on one from the original materials for 6.197 by
# Ceryen Tan and Marek Olszewski.)
OLDMODE=$(shell cat .buildmode 2> /dev/null)
ifeq ($(DEBUG),1)
CFLAGS := $(CFLAGS_DEBUG) $(CFLAGS)
ifneq ($(OLDMODE),debug)
$(shell echo debug > .buildmode)
endif
else ifeq ($(ASAN),1)
CFLAGS := $(CFLAGS_ASAN) $(CFLAGS)
LDFLAGS := $(LDFLAGS) -fsanitize=address
ifneq ($(OLDMODE),asan)
$(shell echo asan > .buildmode)
endif
else
CFLAGS := $(CFLAGS_RELEASE) $(CFLAGS)
ifneq ($(OLDMODE),nodebug)
$(shell echo nodebug > .buildmode)
endif
endif
# When you invoke make without an argument, make behaves as though you had
# typed "make all", and builds whatever you have listed here. (It knows to
# pick "make all" because "all" is the first rule listed.)
all: $(PRODUCT)
# This special "target" will remove the binary and all intermediate files.
clean::
rm -f $(OBJ) $(PRODUCT) .buildmode \
$(addsuffix .gcda, $(basename $(SRC))) \
$(addsuffix .gcno, $(basename $(SRC))) \
$(addsuffix .gcov, $(SRC) fasttime.h)
# This rule generates a list of object names. Each of your source files (but
# not your header files) produces a single object file when it's compiled. In
# a later step, all of those object files are linked together to produce the
# binary that you run.
OBJ = $(addsuffix .o, $(basename $(SRC)))
# These rules tell make how to automatically generate rules that build the
# appropriate object-file from each of the source files listed in SRC (above).
%.o : %.c .buildmode
$(CC) $(CFLAGS) -c $< -o $@
%.o : %.cc .buildmode
$(CC) $(CFLAGS) -c $< -o $@
%.o : %.cpp .buildmode
$(CC) $(CFLAGS) -c $< -o $@
# This rule tells make that it can produce your binary by linking together all
# of the object files produced from your source files and any necessary
# libraries.
$(PRODUCT): $(OBJ) .buildmode
$(CC) -o $@ $(OBJ) $(LDFLAGS)

View file

@ -0,0 +1,95 @@
/**
* Copyright (c) 2014 MIT License by 6.172 Staff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
**/
#ifndef INCLUDED_FASTTIME_DOT_H
#define INCLUDED_FASTTIME_DOT_H
#include <assert.h>
#ifdef __MACH__
#include <mach/mach_time.h> // mach_absolute_time
typedef uint64_t fasttime_t;
// Return the current time.
static inline fasttime_t gettime(void) {
return mach_absolute_time();
}
// Return the time different between the start and the end, as a float
// in units of seconds. This function does not need to be fast.
// Implementation notes: See
// https://developer.apple.com/library/mac/qa/qa1398/_index.html
static inline double tdiff(fasttime_t start, fasttime_t end) {
static mach_timebase_info_data_t timebase;
int r = mach_timebase_info(&timebase);
assert(r == 0);
fasttime_t elapsed = end-start;
double ns = (double)elapsed * timebase.numer / timebase.denom;
return ns*1e-9;
}
static inline unsigned int random_seed_from_clock(void) {
fasttime_t now = gettime();
return (now & 0xFFFFFFFF) + (now>>32);
}
#else // LINUX
// We need _POSIX_C_SOURCE to pick up 'struct timespec' and clock_gettime.
// #define _POSIX_C_SOURCE 200809L
#include <time.h>
typedef struct timespec fasttime_t;
// Return the current time.
static inline fasttime_t gettime(void) {
struct timespec s;
#ifdef NDEBUG
clock_gettime(CLOCK_MONOTONIC, &s);
#else
int r = clock_gettime(CLOCK_MONOTONIC, &s);
assert(r == 0);
#endif
return s;
}
// Return the time different between the start and the end, as a float
// in units of seconds. This function does not need to be fast.
static inline double tdiff(fasttime_t start, fasttime_t end) {
return end.tv_sec - start.tv_sec + 1e-9*(end.tv_nsec - start.tv_nsec);
}
static inline unsigned int random_seed_from_clock(void) {
fasttime_t now = gettime();
return now.tv_sec + now.tv_nsec;
}
// Poison these symbols to help find portability problems.
int clock_gettime(clockid_t, struct timespec *) __attribute__((deprecated));
time_t time(time_t *) __attribute__((deprecated));
#endif // LINUX
#endif // INCLUDED_FASTTIME_DOT_H

View file

@ -0,0 +1,96 @@
/**
* Copyright (c) 2012 MIT License by 6.172 Staff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
**/
#include "./matrix_multiply.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <math.h>
#include <string.h>
// #include "./tbassert.h"
// Allocates a row-by-cols matrix and returns it
matrix* make_matrix(int rows, int cols) {
matrix* new_matrix = malloc(sizeof(matrix));
// Set the number of rows and columns
new_matrix->rows = rows;
new_matrix->cols = cols;
// Allocate a buffer big enough to hold the matrix.
new_matrix->values = (int**)malloc(sizeof(int*) * rows);
for (int i = 0; i < rows; i++) {
new_matrix->values[i] = (int*)malloc(sizeof(int) * cols);
}
return new_matrix;
}
// Frees an allocated matrix
void free_matrix(matrix* m) {
for (int i = 0; i < m->rows; i++) {
free(m->values[i]);
}
free(m->values);
free(m);
}
// Print matrix
void print_matrix(const matrix* m) {
printf("------------\n");
for (int i = 0; i < m->rows; i++) {
for (int j = 0; j < m->cols; j++) {
printf(" %3d ", m->values[i][j]);
}
printf("\n");
}
printf("------------\n");
}
// Multiply matrix A*B, store result in C.
int matrix_multiply_run(const matrix* A, const matrix* B, matrix* C) {
/*
tbassert(A->cols == B->rows,
"A->cols = %d, B->rows = %d\n", A->cols, B->rows);
tbassert(A->rows == C->rows,
"A->rows = %d, C->rows = %d\n", A->rows, C->rows);
tbassert(B->cols == C->cols,
"B->cols = %d, C->cols = %d\n", B->cols, C->cols);
*/
for (int i = 0; i < A->rows; i++) {
for (int j = 0; j < B->cols; j++) {
for (int k = 0; k < A->cols; k++) {
C->values[i][j] += A->values[i][k] * B->values[k][j];
}
}
}
return 0;
}

View file

@ -0,0 +1,58 @@
/**
* Copyright (c) 2012 MIT License by 6.172 Staff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
**/
/**
* Matrix Multiply
*
*
* Declarations here are your API specification -- we expect that your
* code defines and correctly implements these functions and does not modify
* the way the reference implementation uses variables mentioned here,
* so that we may call them from testbed.c and any other testing software
* that we write!
*
* Deviating from this API may cause your program to fail all of our tests.
**/
#ifndef MATRIX_MULTIPLY_H_INCLUDED
#define MATRIX_MULTIPLY_H_INCLUDED
typedef struct {
int rows;
int cols;
int** values;
} matrix;
// Multiply matrix A*B, store result in C.
int matrix_multiply_run(const matrix* A, const matrix* B, matrix* C);
// Allocates a row-by-cols matrix and returns it
matrix* make_matrix(int rows, int cols);
// Frees an allocated matrix
void free_matrix(matrix* m);
// Print matrix
void print_matrix(const matrix* m);
#endif // MATRIX_MULTIPLY_H_INCLUDED

View file

@ -0,0 +1,73 @@
/**
* Copyright (c) 2014 MIT License by Tao B. Schardl
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
**/
#ifndef _TBASSERT_H_
#define _TBASSERT_H_ 1
#ifndef NDEBUG
/**************************************************************************
* Library of debugging macros.
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
// Print a message to STREAM when DEBUG = 1. This macro takes the
// same arguments as FPRINTF().
#define DEBUG_FPRINTF(STREAM, ...) \
do { \
fprintf(STREAM, "%s:%d (%s) ", \
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
fprintf(STREAM, __VA_ARGS__); \
} while (0)
// Print a message to STDERR when DEBUG = 1. This macro takes the
// same arguments as PRINTF().
#define DEBUG_EPRINTF(...) DEBUG_FPRINTF(stderr, __VA_ARGS__);
// If PREDICATE is true, do nothing. Otherwise, print an error with
// the specified message to STDERR. This macro only operates when
// DEBUG = 1. This macro takes a PREDICATE to evaluate followed by
// the standard arguments to PRINTF().
#define DEBUG_ASSERT(PREDICATE, ...) \
do { \
if (!(PREDICATE)) { \
fprintf(stderr, "%s:%d (%s) Assertion " #PREDICATE " failed: ", \
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
fprintf(stderr, __VA_ARGS__); \
abort(); \
} \
} while (0)
#define tbassert DEBUG_ASSERT
#else
#define DEBUG_PRINTF(...) // Nothing.
#define DEBUG_EPRINTF(...) // Nothing.
#define DEBUG_ASSERT(...) // Nothing.
#define tbassert(...) // Nothing.
#endif
#endif // _TBASSERT_H_

View file

@ -0,0 +1,154 @@
/**
* Copyright (c) 2012 MIT License by 6.172 Staff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
**/
/**
* testbed.c:
*
* This file runs your code, timing its execution and printing out the result.
**/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "./fasttime.h"
#include "./matrix_multiply.h"
int main(int argc, char** argv) {
int optchar = 0;
int show_usec = 0;
int should_print = 0;
int use_zero_matrix = 0;
// Always use the same seed, so that our tests are repeatable.
unsigned int randomSeed = 1;
matrix* A;
matrix* B;
matrix* C;
const int kMatrixSize = 4;
// Parse command line arguments
while ((optchar = getopt(argc, argv, "upz")) != -1) {
switch (optchar) {
case 'u':
show_usec = 1;
break;
case 'p':
should_print = 1;
break;
case 'z':
use_zero_matrix = 1;
break;
default:
printf("Ignoring unrecognized option: %c\n", optchar);
continue;
}
}
// This is a trick to make the memory bug leads to a wrong output.
int size = sizeof(int) * 4;
int* temp[20];
for (int i = 0; i < 20; i++) {
temp[i] = (int*)malloc(size);
memset(temp[i], 1, size);
}
int total = 0;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 4; j++) {
total += temp[i][j];
}
}
if (!total) printf("Trick to stop mallocs from being optimized out.");
for (int i = 0; i < 20; i++) {
free(temp[i]);
}
fprintf(stderr, "Setup\n");
A = make_matrix(kMatrixSize, kMatrixSize+1);
B = make_matrix(kMatrixSize, kMatrixSize);
C = make_matrix(kMatrixSize, kMatrixSize);
if (use_zero_matrix) {
for (int i = 0; i < A->rows; i++) {
for (int j = 0; j < A->cols; j++) {
A->values[i][j] = 0;
}
}
for (int i = 0; i < B->rows; i++) {
for (int j = 0; j < B->cols; j++) {
B->values[i][j] = 0;
}
}
} else {
for (int i = 0; i < A->rows; i++) {
for (int j = 0; j < A->cols; j++) {
A->values[i][j] = rand_r(&randomSeed) % 10;
}
}
for (int i = 0; i < B->rows; i++) {
for (int j = 0; j < B->cols; j++) {
B->values[i][j] = rand_r(&randomSeed) % 10;
}
}
}
if (should_print) {
printf("Matrix A: \n");
print_matrix(A);
printf("Matrix B: \n");
print_matrix(B);
}
fprintf(stderr, "Running matrix_multiply_run()...\n");
fasttime_t time1 = gettime();
matrix_multiply_run(A, B, C);
fasttime_t time2 = gettime();
if (should_print) {
printf("---- RESULTS ----\n");
printf("Result: \n");
print_matrix(C);
printf("---- END RESULTS ----\n");
}
if (show_usec) {
double elapsed = tdiff(time1, time2);
printf("Elapsed execution time: %f usec\n",
elapsed * (1000.0 * 1000.0));
} else {
double elapsed = tdiff(time1, time2);
printf("Elapsed execution time: %f sec\n", elapsed);
}
return 0;
}

52
ocw/1/sizes.s Normal file
View file

@ -0,0 +1,52 @@
.file "sizes.c"
.text
.globl subprocedure
.type subprocedure, @function
subprocedure:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
movl -20(%rbp), %edx
movl -24(%rbp), %eax
addl %edx, %eax
movl %eax, -4(%rbp)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size subprocedure, .-subprocedure
.globl main
.type main, @function
main:
.LFB7:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $3, -8(%rbp)
movl $5, -4(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %esi
movl %eax, %edi
call subprocedure
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE7:
.size main, .-main
.ident "GCC: (GNU) 15.1.1 20250425"
.section .note.GNU-stack,"",@progbits

BIN
ocw/bit-hacks/a.out Executable file

Binary file not shown.

2
ocw/bit-hacks/a.py Normal file
View file

@ -0,0 +1,2 @@
class S:
def __init__(self)

View file

@ -0,0 +1,2 @@
-O2
-masm=intel

12
ocw/bit-hacks/hacks.cc Normal file
View file

@ -0,0 +1,12 @@
#include <iostream>
int main() {
int x = 123;
int y = 123123;
std::cout << x;
std::swap(x, y);
std::cout << y;
return 0;
}

BIN
ocw/bit-hacks/structop Executable file

Binary file not shown.

15
ocw/bit-hacks/structop.cc Normal file
View file

@ -0,0 +1,15 @@
#include <cstddef>
#include <iostream>
struct S {
char b;
int i;
};
int main() {
S s;
std::cout << offsetof(S, i) << '\n';
return 0;
}

BIN
ocw/profiling/a.out Executable file

Binary file not shown.

File diff suppressed because it is too large Load diff

89225
ocw/profiling/demangled.s Normal file

File diff suppressed because it is too large Load diff

39
ocw/profiling/notes.md Normal file
View file

@ -0,0 +1,39 @@
# profiling
## intro
### instrumentation: overall timing (usual idea)
- while timing a clock with `time_the_clock.cc`, i erroneously initialized a
`chrono::microseconds` default. this can be seen in the STL source: the default constructor
initializes the `Rep` (repeated value, the unit for the duration) by
default. A `microsecond` is a long here - this became garbage.
- NOTE: timing the clock (with 0 optimization) took ~0ns and is not of significance for my profiling. I concluded this by compiling with `-O0` and de-mangling with c++filt we can see this is the case: we can see this is the case and nothing is being optimized out:
```asm
.L585:
call std::chrono::_V2::system_clock::now()@PLT
movq %rax, -64(%rbp)
call std::chrono::_V2::system_clock::now()@PLT
```
However, I acknowledge that this code is not run one-for-one. I don't have the
knowledge to assess caching done by the actual CPU itself, or even other side
effects like inlining.
So far, though, one lesson of profiling is:
> Only profile the code *actually* being profiled
### statistical profiling
- more accurate by *experimental* virtue - probabilistic look
- imagine the execution of the program as a "strip" of time
- system-specific, but so was before
- statistical: stats
- program simulation: ll
## exercise 1
- use cachegrind/valgrind/asan on cf problem
- apply bentley's rules to some code
- begin developing a strategy for how to profile things

26698
ocw/profiling/output.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
ocw/profiling/perf-tester Executable file

Binary file not shown.

View file

@ -0,0 +1,19 @@
#include <iostream>
void complex_method() {
int i = 0x12323333- 1230*123213;
long x = -23;
std::cout << "x: " << x << '\n';
while (--i) {
x ^= (x - 1);
for (int j = 0; j < 50; ++j) {
x = x * x * x;
}
}
}
int main() {
complex_method();
return 0;
}

BIN
ocw/profiling/perf.data Normal file

Binary file not shown.

BIN
ocw/profiling/perf.data.old Normal file

Binary file not shown.

114179
ocw/profiling/perf.script Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
#include <chrono>
#include <iostream>
#include <print>
using namespace std;
constexpr static size_t TRIALS = 100000;
int main() {
chrono::microseconds diffs_ms{0};
for (size_t loop_var = 1; loop_var <= TRIALS; ++loop_var) {
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
diffs_ms += chrono::duration_cast<chrono::microseconds>(t2 - t1);
}
print("measuring the clock in c++ 23 {} trials had an average time duration "
"of: {} microseconds, or {} milliseconds",
TRIALS, diffs_ms / TRIALS,
chrono::duration_cast<chrono::milliseconds>(diffs_ms / TRIALS));
return 0;
}

89225
ocw/profiling/time_the_clock.s Normal file

File diff suppressed because it is too large Load diff