Showing posts with label books. Show all posts
Showing posts with label books. Show all posts

Oct 19, 2022

[book][notes] The art of writing efficient programs - Fedor

Reference:

The Google CPU profiler also uses hardware performance counters and requires
link-time instrumentation of the code.
$ clang++ -g -O3 -mavx2 -Wall -pendantic x1.cpp x2.cpp -lprofiler -o example
$ CPUPROFILE=prof.data CPUPROFILE_FREQUENCY=1000 ./example
$ google-pprof --text ./example prof.data
$ google-pprof --text --lines ./example prof.data
$ google-pprof --pdf ./example prof.data > prof.pdf

$ perf stat ./example
$ perf list // list counter type
$ perf -e counter types ./example
$ perf record -c sampling_count ./example
$ perf report // report the prof.data
$ perf stat -e cycles,instructions,L1-dcache-load-misses,L1-dcache-loads ./program

Profiling for branch mispredictions:
$ perf stat ./benchmark
First generates the report
$ perf record -e branches,branch-misses ./benchmark // perf --list gets the -e arguments
Then read it:
$ perf report


Micro-benchmark example:
system_clock::time_point t1 = system_clock::now();

// Our code

system_clock::time_point t2 = system_clock::now();
cout << "Sort time: " <<
duration_cast<milliseconds>(t2 - t1).count() << "ms (" << count << " comparisons)" << endl;
auto t0 = system_clock::now();
// ... do some work ...
auto t1 = system_clock::now();
auto delta_t = duration_cast(t1 – t0);
cout << "Time: " << delta_t.count() << endl;

clock_gettime used in linux only.
Be ware, take care to subtract seconds first and only then add nanoseconds, otherwise, you lose significant digits of the result by subtracting two large numbers.
If the reported CPU time does not match the real time, it is likely that the machine is overloaded (many other processes are competing for the CPU resources), or the program is running out of memory (if the program uses more memory than the physical memory on the machine, it will have to use the much slower disk swap, and the CPUs can't do any work while the program is waiting for the memory to be paged in from disk).
double duration(timespec a, timespec b) {
return a.tv_sec - b.tv_sec + 1e-9*(a.tv_nsec - b.tv_nsec);
}

{
timespec rt0, ct0, tt0;
clock_gettime(CLOCK_REALTIME, &rt0);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ct0);
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tt0);

// Code
constexpr double X = 1e6;
double s = 0;
for (double x = 0; x < X; x += 0.1) s += sin(x);
// Code end

timespec rt1, ct1, tt1;

clock_gettime(CLOCK_REALTIME, &rt1);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ct1);
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tt1);

cout << "Real time: " << duration(rt1, rt0) << "s, "
"CPU time: " << duration(ct1, ct0) << "s, "
"Thread time: " << duration(tt1, tt0) << "s" << endl;
}
The CMOVcc instructions don't compare the source and destination. They use the flags from a previous comparison (or other operation that sets the flags) which determines if the move should be done or not. 
This prevents branch miss. (compiler uses cmove for ternary operator)
e.g. this copies edx to ecx if eax and ebx are equal:
cmp eax, ebx
cmove ecx, edx
same as:
cmp eax, ebx
jne skip
  mov ecx, edx
skip:

As long as the operands are already in the registers, the processor can execute several operations at once.
e.g.
void BM_add_multiply(benchmark::State& state) {
... prepare data ...
for (auto _ : state) {
	unsigned long a1 = 0, a2 = 0;
	for (size_t i = 0; i < N; ++i) {
		a1 += p1[i] + p2[i]; // p1[i] and p2[i] are inside the register
		a2 += p1[i] * p2[i]; // p1[i] and p2[i] are inside the register, 
		// thus adding a2 has no performance hit; same as running a1 only.
	}	
	benchmark::DoNotOptimize(a1);
	benchmark::DoNotOptimize(a2);
	benchmark::ClobberMemory();
}

state.SetItemsProcessed(N*state.iterations());
}
There is a limit to how many operations can be executed:
the processor has only so many execution units capable of doing integer computations.
Still, it is instructive to try to push the CPU to its limits by adding more and more instructions to one iteration.
Be ware of data dependency. This would add extra cycles to the processing. (CS architecture 101; pipeline)

Use MCA:
#define MCA_START __asm volatile("# LLVM-MCA-BEGIN");
#define MCA_END __asm volatile("# LLVM-MCA-END");
...
for (size_t i = 0; i < N; ++i) {
	MCA_START
	a1 += p1[i] + p2[i];
	MCA_END
}
$ clang++ -std=c++20 benchmark.cpp -g -O3 -mavx2 -mllvm -x86-asm-syntax=intel -S -o - | llvm-mca -mcpu=btver2 -timeline


Can we benchmark memory access speed through below code? Nope; due to we have store-buffer,L1/L2/L3 cache in front of the memory (to CPU).
volatile int* p = new int;
*p = 42;
for (auto _ : state) {
	benchmark::DoNotOptimize(*p);
    //... repeat access *p 32 times ...
    benchmark::DoNotOptimize(*p);
}
state.SetItemsProcessed(32*state.iterations());
delete p;

Test read/write memory including L1/L2/L3/Memory:
#define REPEAT2(x) x x
#define REPEAT4(x) REPEAT2(x) REPEAT2(x)
#define REPEAT8(x) REPEAT4(x) REPEAT4(x)
#define REPEAT16(x) REPEAT8(x) REPEAT8(x)
#define REPEAT32(x) REPEAT16(x) REPEAT16(x)
#define REPEAT(x) REPEAT32(x)

template <class Word>
void BM_read_seq(benchmark::State& state) {
    const size_t size = state.range(0);
    void* memory = ::malloc(size);
    void* const end = static_cast<char*>(memory) + size;
    volatile Word* const p0 = static_cast<Word*>(memory);
    Word* const p1 = static_cast<Word*>(end);
    for (auto _ : state) {
        for (volatile Word* p = p0; p != p1; ) {
            REPEAT(benchmark::DoNotOptimize(*p++);)
        }
        benchmark::ClobberMemory();
    }

    Word fill = {};
    // Default-constructed
    for (auto _ : state) {
        for (volatile Word* p = p0; p != p1; ) {
            REPEAT(benchmark::DoNotOptimize(*p++ = fill);)
        }
        benchmark::ClobberMemory();
    }
::free(memory);
state.SetBytesProcessed(size*state.iterations());
state.SetItemsProcessed((p1 - p0)*state.iterations());
}

#define ARGS ->RangeMultiplier(2)->Range(1<<10, 1<<30)
BENCHMARK_TEMPLATE1(BM_read_seq, unsigned int) ARGS;
BENCHMARK_TEMPLATE1(BM_read_seq, unsigned long) ARGS;

// for SSE(16 bytes) and AVX(32 bytes) instructions
#include <emmintrin.h>
#include <immintrin.h>
BENCHMARK_TEMPLATE1(BM_read_seq, __m128i) ARGS;
BENCHMARK_TEMPLATE1(BM_read_seq, __m256i) ARGS;

Spectre attack, Fedor did a great explain about the notorious Spectre attack,


Aug 23, 2021

[TDD][book note] Modern C++ programming with TDD

Section 1

Managing test lists is particularly useful.

Uncle Bob describes TDD with three rules:
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

i.e
- Write only enough of a unit test to fail.
- Write only enough production code to make the failing unit test pass.

One assert per test. One behavior per test.

Use expect_that instead of assert.

Follow the Single Responsibility Principle(SRP).


Section 2

Unit test:
1. (Optional) statements that set up a context for execution.
2. One or more statements to invoke the behavior you want to verify.
3. One or more statements to verify the expected outcome.
4. (Optional) cleanup statements.


Section 3

TDD cycle

Red-Green-Refactor
1. write a test(Red)
2. Get the test to pass(Green)
3. Optimize the design(Refactor)

Test behavior, not methods.
Keep it simple.
Sticking to the cycle.

In unit test

Arrange-Act-Assert / Given-When-Then

In TDD, unit test should be FAST. i.e no datbase/IO access as possible;
those tests belongs to integration test.

GTest allows you to run subset of the tests by passing in argument to the test binary.
e.g (RTFM)
./test --gtest_filter=MyTest.*


Test private data member

Don't. Violates Tell-Don't-Ask design. If must; add an accessor with returned copy of that value.


Section 4

Test doubles(In C++, we have several choices. Inheritance, template, CRTP, injection.


Section 5

Quality test

Fast
Isolated
Repeatable
Self-verifying
Timely


Section 6

Threading/Concurrent code

1. Separate threading logic from application logic.
2. Sleep is bad.
3. Throttle down to single-threaded for application-specific tests.
4. Demonstrate concurrency issues before introducing concurrency controls.(Hmm...)

Feb 7, 2016

[reading] A Book Forged In Hell - Prologe and Chapter 1.

The vilest hypocrites, urged on by that same fury which they call zeal for God's law, have everywhere prosecuted men whose blameless character and distinguished qualities have excited the hostility of the masses, publicly denouncing their beliefs and inflaming the savage crowd's anger against them. And this shameless license, sheltering under the cloak of religion, is not easy to suppress. - Spinoza

----------

Mar 7, 2012

[UNIX Programming] Books reading


Advanced Programming in the UNIX Environment, Second Edition

I have the first edition of this book when I was in college.
It's nice, precise, informative.
The second edition also adds in the API difference between unix and Linux, which is great.
I read this book several times, especially the process chapter. A must have book for unix programming

The Linux Programming Interface: A Linux and UNIX System Programming Handbook

Well,well,well~~ Another classic unix/linux programming book. Love it, more detailed in API explanation and design info than "Advanced Programming in the UNIX Environment, Second Edition".

Pthreads Programming: A POSIX Standard for Better Multiprocessing

Tedious. But over all a nice book..

[software engineering] books read


Design Patterns: Elements of Reusable Object-Oriented Software

I've got this book long time ago, even before I am really into C++.
This book is based on the C++ language.
There are a lot of techniques are based on C++ language features, now when I re-read it, it makes more sense.
It's not a entry level book for DP, and I believe basing on which language you use, you should read a DP book written in that language. Although the general concepts are the same, but implementation details are totally different.

The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition

Mar 2, 2012

[network] Books reading


TCP/IP Illustrated, Volume 1: The Protocols (2nd Edition)

Kevin R. Fall did a great job in updating this classic book.
The 2nd edition not only included IPv6, but updated lots of details in TCP congestion control, alone with ICMP infos. It also gives more details than the 1st edition and make this classic more clear than ever.

Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition)

THE BEST book for network programming.
Although there are many chapters talking about SCTP which I don't see else where using it(I am not encountering any, though), the book is GREAT in details.

Sep 8, 2011

[C++] Books read, the verbalsaint's C++ Learning path


C++ Primer 4th edition

Basic syntax and pitfalls, most of the information mentioned in Effective C++ and other C++ SYNTAX related books are in this book. However, those content mentioned in other books are scattered in this book, if you want to have a systematic learning of those great ideas, Effective C++ is the book that you should read. This is a good reference book if you are not familiar with C++ syntax.

Inside the C++ Object Model

A MUST READ. Understanding how compiler generate codes and the concepts why it does that. I had this book in Traditional Chinese (Taiwan,ROC) version. It's translated by JJHou(侯捷), whom also fixed LOT's of typos in the English version which makes it more comfortable to read.

Effective C++: 55 Specific Ways to Improve Your Programs and Designs

A guide for starter.

C++ Templates: The Complete Guide

A MUST READ!! Although this book needs to be updated with the new C++0X standard, however, it's still the best template book out there.

Modern C++ Design: Generic Programming and Design Patterns Applied

Before reading this book, MUST READ C++ Templates: The Complete Guide, otherwise, you'll be just wasting time with trial and error.

Essential COM

To code in MS COM, this book is a MUST READ. Also, there are good coding standards to follow even we don't code in COM. API is outdated, but the ideas still apply.

C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond

Book content also available on boost web site

API Design for C++

OK to read if have time.

Introduction to the Boost C++ Libraries; Volume I - Foundations

C++ Concurrency in Action: Practical Multithreading

Currently the only book delves into C++11 thread and memory model. MUST READ if working with C++11.

Advanced C++ Metaprogramming

I did report some typo of this book , and got a free copy of the pdf version from the author, YA!!

Secure Coding in C and C++

The C++ Standard Library: A Tutorial and Reference

A MUST READ. Great reference book also. The new edition is coming out on 2012.April. Updated with C++11, looking forward to get my copy!!
UPDATE! My copy of the book has arrived!! Start reading!

Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library

A MUST read for STL, it has info about STL's algorithms and implementation. MUST READ!!

Presentation Materials: Effective C++ in an Embedded Environment

C++'s flexibility, modelling power, support for object-oriented and generic programming, and extensive tool set, make it attractive for embedded projects, but some developers worry about code bloat and hidden performance penalties. This seminar begins by confronting those issues directly, then moves on to demonstrate how C++ can improve the correctness, readability, and efficiency of embedded software, in some cases accomplishing what is literally impossible in C.
C++ Gotchas: Avoiding Common Problems in Coding and Design
Kinda like Java Puzzlers: Traps, Pitfalls, and Corner Cases book for C++. Give lots of information about coding details. Nice book!

=============================
 C++11 


Presentation Materials: Overview of the New C++ (C++11)

Specification of the new version of C++ (“C++11”) is finally complete, and many compilers (e.g., Visual C++ and Gnu C++) already offer many features from the revised language. And such features! auto-declared variables reduce typing drudgery and syntactic noise; Unicode and threading support address important functionality gaps; and rvalue references and variadic templates facilitate the creation of more efficient, more flexible libraries. The standard library gains resource-managing smart pointers, new containers, additional algorithms, support for regular expressions, and more. Altogether, C++11 offers much more than “old” C++. This intensively technical seminar introduces the most important new features in C++11 and explains how to get the most out of them.
===============================
Article :

C++11 FAQ

C++0x - the next ISO C++ standard
Lambdas, auto, and static_assert: C++0x Features in VC10, Part 1
Rvalue References: C++0x Features in VC10, Part 2
decltype: C++0x Features in VC10, Part 3

Last but not least,
Andrei Alexandrescu's papers and articles :-)