Skip to content

Instantly share code, notes, and snippets.

@tell
Last active October 8, 2015 15:06
Show Gist options
  • Save tell/0faf48c4445634ce7297 to your computer and use it in GitHub Desktop.
Save tell/0faf48c4445634ce7297 to your computer and use it in GitHub Desktop.
Atomic vs Mutex
#include <stdio.h>
#include <thread>
#include <mutex>
#include <atomic>
#define XBYAK_NO_OP_NAMES
#include <xbyak/xbyak_util.h>
const int N = 10000000;
void loop(void f())
{
for (int i = 0; i < N; i++) {
f();
}
}
int ni;
void none_inc() { ni++; }
int none_get() { return ni; }
std::atomic<int> ai;
void atomic_inc() { ai++; }
int atomic_get() { return (int)ai; }
std::atomic<int> bi;
void atomic_inc2() { bi++; }
int mi;
std::mutex m;
void mutex_inc()
{
std::lock_guard<std::mutex> al(m);
mi++;
}
int mutex_get() { return mi; }
int mi2;
std::mutex m2;
void mutex_inc2()
{
std::lock_guard<std::mutex> al(m2);
mi2++;
}
void bench(const char *msg, void f(), int get(), void f2() = 0)
{
Xbyak::util::Clock clk;
clk.begin();
std::thread t1(loop, f);
std::thread t2(loop, f2 ? f2 : f);
t1.join();
t2.join();
clk.end();
printf("%s=%d\n", msg, get());
printf("clk=%f\n", clk.getClock() / double(N));
}
int main()
{
bench("none ", none_inc, none_get);
bench("atomic", atomic_inc, atomic_get);
bench("mutex ", mutex_inc, mutex_get);
bench("atomic not conflict", atomic_inc, atomic_get, atomic_inc2);
bench("mutex not conflict", mutex_inc, mutex_get, mutex_inc2);
}
#include <cstdio>
#include <thread>
#include <boost/thread/barrier.hpp>
#define XBYAK_NO_OP_NAMES
#include <xbyak/xbyak_util.h>
const int T = 2;
const int N = 10000000;
int v[T + 2];
int w[T + 2];
void loop(void func(const int), const int id)
{
for (int i = 0; i < N; i++) {
func(id);
}
}
void f(const int id) {
#if 0
w[id] = v[id - 1] + v[id] + v[id + 1];
v[id] = w[id - 1] + w[id] + w[id + 1];
#else
v[id]++;
#endif
}
boost::barrier br(T);
void g(const int id) {
#if 0
w[id] = v[id - 1] + v[id] + v[id + 1];
br.wait();
v[id] = w[id - 1] + w[id] + w[id + 1];
br.wait();
#else
v[id]++;
br.wait();
#endif
}
void bench(const char *msg, void f(const int))
{
printf("%s\n", msg);
for (int i = 0; i < T + 2; i++) {
v[i] = i;
}
std::thread ts[T];
Xbyak::util::Clock clk;
clk.begin();
for (int i = 0; i < T; i++) {
ts[i] = std::thread(loop, f, i + 1);
}
for (int i = 0; i < T; i++) {
ts[i].join();
}
clk.end();
for (int i = 0; i < T + 2; i++) {
printf("v[%d]=%d\n", i, v[i]);
}
printf("clk=%f\n", clk.getClock() / double(N));
}
int main()
{
printf("hc = %u\n", std::thread::hardware_concurrency());
bench("none", f);
bench("barrier", g);
}
#define XBYAK_NO_OP_NAMES
#include <xbyak/xbyak_util.h>
#include "throw-catch.hpp"
const int N = 1000000;
int numthrow, nothrow;
void loop(bool func(const int)) {
for (int i = 0; i < N; i++) {
if (func(i))
numthrow++;
else
nothrow++;
}
}
void bench(const char *msg, bool func(const int)) {
numthrow = nothrow = 0;
Xbyak::util::Clock clk;
clk.begin();
loop(func);
clk.end();
const int sum = numthrow + nothrow;
const double ratio = double(numthrow) / double(sum);
#if 0
printf("%s: numthrow=%d, nothrow=%d, ratio=%.3f, sum=%d\n",
msg, numthrow, nothrow, ratio, sum);
#else
printf("%s: ratio=%.3f\n", msg, ratio);
#endif
printf("clk=%f\n", clk.getClock() / double(N));
}
int main() {
bench("none", Func<10>::normalfunc);
bench("none", Func<50>::normalfunc);
bench("none", Func<90>::normalfunc);
bench("throw-catch", Func<10>::catchfunc);
bench("throw-catch", Func<50>::catchfunc);
bench("throw-catch", Func<90>::catchfunc);
}
CC = $(CXX)
CPPFLAGS += -std=c++11 -pthread -O3 -I$(HOME)/include -I../xbyak
BOOST_SUFFIX =
WORKAROUND_LDLIBS =
ifeq ($(shell uname -s),Darwin)
BOOST_SUFFIX = -mt
endif
ifneq (,$(findstring Linux,$(shell uname -s)))
# See http://stackoverflow.com/questions/22593658/compiling-multithread-code-with-g-wl-no-as-needed-not-working
# and https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1228201
WORKAROUND_LDLIBS = -Wl,--no-as-needed
endif
ifneq (,$(findstring CYGWIN,$(shell uname -s)))
BOOST_SUFFIX = -1_55
endif
LDFLAGS += -L$(HOME)/lib -L/usr/bin
LDLIBS += $(addsuffix $(BOOST_SUFFIX),-lboost_thread -lboost_system) -lpthread $(WORKAROUND_LDLIBS)
TARGETS = atomic_vs_mutex barrier_thread main-throw-catch
all: $(TARGETS)
clean:
$(RM) $(TARGETS)
main-throw-catch.o: throw-catch.hpp
#pragma once
template<int Percentage>
struct Func {
static const int NumOfThrow = 10000;
static const int Total = NumOfThrow * 100 / double(Percentage);
static bool throwfunc(const int x) {
if ((x % Total) < NumOfThrow) {
throw std::runtime_error("an input is small.");
}
return false;
}
static bool catchfunc(const int x)
try {
return throwfunc(x);
} catch (...) {
return true;
}
static bool normalfunc(const int x) {
if ((x % Total) < NumOfThrow) {
return true;
} else {
return false;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment