$ cpp -dM /dev/null #define __DBL_MIN_EXP__ (-1021) #define __UINT_LEAST16_MAX__ 65535 #define __FLT_MIN__ 1.17549435082228750797e-38F #define __UINT_LEAST8_TYPE__ unsigned char #define __INTMAX_C(c) c ## L #define __CHAR_BIT__ 8 #define __UINT8_MAX__ 255 #define __WINT_MAX__ 4294967295U #define __ORDER_LITTLE_ENDIAN__ 1234 #define __SIZE_MAX__ 18446744073709551615UL #define __WCHAR_MAX__ 2147483647 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 #define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L) #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 #define __FLT_EVAL_METHOD__ 0 #define __unix__ 1 ...一般说来Linux平台上会预定义__linux__, 而MacOS会预定义__APPLE__
Wednesday, May 22, 2013
查看gcc预定义的macro
在Linux或者MacOS的terminal里运行:
Saturday, April 13, 2013
[C] 线程局部存储 (thread-local storage)
GCC 支持使用线程局部存储(TLS)来方便多线程的编程.通俗来说, TLS就是一些看起来global的变量, 但是它实际上是per-thread的
使用TLS很简单,只需要用__thread关键字来修饰一个"全局变量",比如下面例子里的tid. 它在不同的thread里被输出的时候就是输出不同的值
使用TLS很简单,只需要用__thread关键字来修饰一个"全局变量",比如下面例子里的tid. 它在不同的thread里被输出的时候就是输出不同的值
#include <stdio.h> #include <pthread.h< #define NUM_THREADS 5 __thread long tid; void print_tid() { printf("Hello World! It's me, thread #%ld!\n", tid); } void *run_thread(void *threadid) { tid = (long)threadid; print_tid(); pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t threads[NUM_THREADS]; int rc; long t; for(t=0; t<NUM_THREADS; t++){ rc = pthread_create(&threads[t], NULL, run_thread, (void *)t); if (rc){ printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); } } /* Last thing that main() should do */ pthread_exit(NULL); }运行
$ gcc test_tls.c $ ./a.out Hello World! It's me, thread #0! Hello World! It's me, thread #1! Hello World! It's me, thread #2! Hello World! It's me, thread #3! Hello World! It's me, thread #4!
参考
GCC对TLS的支持Thursday, April 11, 2013
[C/C++] 随机数
C里的RAND
#include <stdlib.h>
#include <stdio.h>
int main()
{
srand(time(0));
printf("%d\n", rand());
return 0;
}
使用C++11 里的Mersenne Twister随机数
C++11支持的Mersenne Twister可以非常轻量级的快速生成大量随机数.适合在benchmark的时候使用
#include <iostream>
#include <random>
main() {
std::mt19937_64 rng;
// 使用系统时间生成随机数种子
rng.seed(static_cast<unsigned int>(std::time(0)));
// 生成32-bit的随机整数
std::cout << rng() << std::endl;
// 生成 1到255之间(包括1和255) 的随机数
std::uniform_int_distribution<int> unif(1, 255);
std::cout << unif(rng)<< std::endl;
// 以概率0.3生成true, 0.7生成false
std::bernoulli_distribution bern(0.3);
std::cout << bern(rng) << std::endl;
}
Saturday, March 30, 2013
code style
Python的code style
Python官方约定的风格PEP 8 -- Style Guide for Python CodeC++的code style
C++并无官方约定的风格。 我一般会遵从 Google 的C++ style guideWednesday, March 27, 2013
在MacOS和Linux上使用Ramdisk
在Linux上使用Ramdisk
我使用如下脚本来生成一个大小可设定的tmpfs作为ramdisk
#!/bin/bash TMPFS_SIZE=12G mkdir -p ./ramdisk sudo umount ./ramdisk >& /dev/null sudo mount -t tmpfs -o size=$TMPFS_SIZE,mode=0775,gid=binfan tmpfs ./ramdisk
在MacOS上使用Ramdisk
创建一个Ramdisk
$ hdiutil attach -nomount ram://1165430 /dev/disk2 $ diskutil erasevolume HFS+ "ramdisk" /dev/disk2 Started erase on disk2 Unmounting disk Erasing Initialized /dev/rdisk2 as a 569 MB HFS Plus volume Mounting disk Finished erase on disk2 ramdisk然后使用df就可以看见这个device了
$ df
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk0s2 818359360 273993824 543853536 34% 34313226 67981692 34% /
devfs 381 381 0 100% 660 0 100% /dev
map -hosts 0 0 0 100% 0 0 100% /net
map auto_home 0 0 0 100% 0 0 100% /home
/dev/disk0s4 156733432 41530424 115203008 27% 108561 57608399 0% /Volumes/BOOTCAMP
localhost:/AI1XeO7VNLFdFPonF9OexW 818359360 818359360 0 100% 0 0 100% /Volumes/MobileBackups
/dev/disk1s1s2 35040 35040 0 100% 8758 0 100% /Volumes/HTC Sync Manager
/dev/disk2 1165424 27376 1138048 3% 3420 142256 2% /Volumes/ramdisk
不用的时候在Finder里面弹出这个设备就可以了.
Sunday, March 03, 2013
Memory barrier, volatile, cache coherency
Linux Kernel关于memory barrier的介绍
volatile会强制在你的code里, 每次都re-read该变量值. 但是它不能控制这个值的来源---可能从memory中读入, 也可能因为你的code刚刚访问过这个变量从而从cache中读入而不是memory.
http://stackoverflow.com/questions/558848/can-i-force-cache-coherency-on-a-multicore-x86-cpu
volatile会强制在你的code里, 每次都re-read该变量值. 但是它不能控制这个值的来源---可能从memory中读入, 也可能因为你的code刚刚访问过这个变量从而从cache中读入而不是memory.
http://stackoverflow.com/questions/558848/can-i-force-cache-coherency-on-a-multicore-x86-cpu
Wednesday, February 27, 2013
Sunday, February 24, 2013
[C++] 小探iterator
#include <iostream>
#include <map>
using namespace std;
main() {
map<int int> a;
map<int int>::const_iterator cit;
map<int int>::iterator it;
a[1] = 15;
printf("&a[1] = %p a[1] = %d\n", &a[1], a[1]);
cit = a.find(1);
it = a.find(1);
it->second = 255;
printf("%lx %p %d\n", *((long*) &it), &(it->second), it->second);
printf("%lx %p %d\n", *((long*) &cit), &(cit->second), cit->second);
}
运行结果:
$ ./a.out &a[1] = 0x7fb58a403954 a[1] = 15 &it =0x7fff520aa898 it =7fb58a403930 &(it->second) =0x7fb58a403954 it->second =255 &cit=0x7fff520aa8a0 cit=7fb58a403930 &(cit->second)=0x7fb58a403954 cit->second=255几个结论:
- 从cit只占用8个字节大小来看(&it-&cit), map::const_iterator 或者map::iterator, 其实内容就是一个8-byte的指针
- 从cit和it都存着同样内容(0x7fff520aa898)来看, 内容其实就是map中该元素的地址.
- 而且iterator的first 和second并不是值拷贝. 比如我们使用it对a[1]的值更新后, const_iterator只是该iterator不能对map做改动而已.
Thursday, February 21, 2013
[Emacs] Doxymacs
C-c d ? will look up documentation for the symbol under the point.
C-c d r will rescan your Doxygen tags file.
C-c d f will insert a Doxygen comment for the next function.
C-c d i will insert a Doxygen comment for the current file.
C-c d ; will insert a Doxygen comment for the current member.
C-c d m will insert a blank multiline Doxygen comment.
C-c d s will insert a blank singleline Doxygen comment.
C-c d @ will insert grouping comments around the current region.
Sunday, February 17, 2013
[Golang] Golang笔记贴(坑)
啥是Go?
Go是Google在09年左右新推出的一门语言.在语法上说, Go有点类似于C.但是Go的特性在于其高并发性和事件处理,使得它特别适合作为分布式编程的语言.CMU的15-440(distributed systems)开始使用Go做教学语言, 结果效果出奇的好.安装设置Go
Go的安装 $GOPATH, $GOROOT如果GOPATH=/path/to/A:/path/to/B, 那么go在找库的时候就从/path/to/A/pkg, /path/to/B/pkg这样的顺序.
安装远端repository里的库
Reference
Go语言简介(上):语法Go语言简介(下):特性
Saturday, February 16, 2013
[Linux] Linux上NUMA相关的命令
查看NUMA的memory设置等
$ cat /sys/devices/system/node/node*/meminfo Node 0 MemTotal: 16777216 kB Node 0 MemFree: 14312 kB Node 0 MemUsed: 16762904 kB ... Node 0 HugePages_Total: 1000 Node 0 HugePages_Free: 744 Node 0 HugePages_Surp: 0 Node 1 MemTotal: 16763940 kB Node 1 MemFree: 5289568 kB Node 1 MemUsed: 11474372 kB ... Node 1 HugePages_Total: 1000 Node 1 HugePages_Free: 1000 Node 1 HugePages_Surp: 0
查看NUMA统计数据
比如多少local node reference, 多少foreign node reference$ cat /sys/devices/system/node/node*/numastat numa_hit 759046092 numa_miss 333483705 numa_foreign 236930883 interleave_hit 12690 local_node 746065583 other_node 346464214 numa_hit 506048971 numa_miss 236930883 numa_foreign 333483705 interleave_hit 12713 local_node 507619074 other_node 235360780
使用numactl设置task的numa属性
prefer(并非强制)使用numa node0来执行my_app$ numactl --preferred=0 ./my_app arg1 arg2强制使用numa node0 的local cpu和local memory来执行my_app
$ numactl --cpubind=0 --membind=0 ./my_app arg1 arg2
Saturday, February 02, 2013
[Latex] 编辑文档的tips
watermark
有时候我们需要在每一页打上一个水印, 这时候可以使用draftwatermark这个package.\usepackage{draftwatermark}
\SetWatermarkText{this is a draft}
\SetWatermarkScale{0.5}
更多的参数可见 http://texblog.org/tag/draftwatermark/还有一个叫draftcopy的package也是可以做类似的事情, 但是似乎在我这里有问题
Friday, January 18, 2013
[Latex] 修补Rubber
Rubber停更很久了,所以已经从我的Latex编译好帮手,堕落为了pain of ass.
比如编译tex文件的时候会出现如下错误导致bib文件不能正确的编译出来:
解决方法: 在bibtex.py(如果你的rubber是使用brew安装的话, 其路径为/usr/local/Cellar/rubber/20100306/share/rubber/rubber/latex_modules/bibtex.py)中修改run这个函数, 在调用Popen前加上:
bibtex 问题
比如编译tex文件的时候会出现如下错误导致bib文件不能正确的编译出来:
running post-compilation scripts... running BibTeX on paper... There were errors making the bibliography. There were errors compiling paper.这是因为, rubber是这样调用bibtex的
Popen(['bibtex /your/path/to/tex/file'])而在新的bibtex中, 不能接受绝对路径作为输入参数
解决方法: 在bibtex.py(如果你的rubber是使用brew安装的话, 其路径为/usr/local/Cellar/rubber/20100306/share/rubber/rubber/latex_modules/bibtex.py)中修改run这个函数, 在调用Popen前加上:
cmd = ["bibtex", "-min-crossrefs=1000", msg.simplify(self.base)] process = Popen(cmd, stdout=PIPE, stderr=PIPE)
Thursday, September 27, 2012
[Linux] Bash tips
bang bang
$ !!执行上一个命令
$ !x执行上一个以"x"开头的命令
$ !xyz执行上一个以"xyz"开头的命令
bang dollar
$ cat ~git/repository/foo.git/hooks/post-receive $ vi !$!$会被扩展为上一个命令的最后一个argument
类似的!*会被扩展为上一个命令的所有argument
dollar bang
$ ./exe_something & $ LAST_PID= $!$!为上一个命令的PID
dollar question-mark
$ ./exe_something $ echo $?$?为上一个命令的exit状态
Sunday, August 12, 2012
[Linux] backtrace
使用gdb可以在断点处停下来从而允许我们查看call strack. 可是有时候我们希望在程序里自动的显示当前的call stack --- 比如在异常的时候写到log当中.这时候就需要使用backtrace:
1 使用backtrace
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
显示出当前call stack 的backtrace: 每一行为一个frame对应的binary和在binary中的地址
addr2line将binary的相对offset地址转化为对应的文件以及行数
1 使用backtrace
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
显示出当前call stack 的backtrace: 每一行为一个frame对应的binary和在binary中的地址
Obtained 7 stack frames. /home/foo/bench_cache() [0x4050f5] /home/foo/bench_cache() [0x405f4e] /home/foo/bench_cache() [0x407d8d] /home/foo/bench_cache() [0x40283a] /home/foo/bench_cache() [0x402e13] /lib/libc.so.6(__libc_start_main+0xfe) [0x7fad2481dd8e] /home/foo/bench_cache() [0x401eb9]2 使用addrline
addr2line将binary的相对offset地址转化为对应的文件以及行数
$ addr2line -e bench_cache -f 0x4050f5 print_backtrace /home/foo/bench_util.h:28参数:
- -e binary, 指定对应的binary
- -f, 显示对应的function名称
gmail advanced search tips
http://support.google.com/mail/bin/answer.py?hl=en&answer=7190&topic=1668965&ctx=topic
Saturday, August 11, 2012
Raspberry Pi
下载并解压, 得到 2012-07-15-wheezy-raspbian.img
你需要把这个img考到你的SD卡当中.
在MacOS中:
使用update-rc
http://www.debian-administration.org/articles/28
$ diskutil list比如你的SD是/dev/disk1的话
$ diskutil unmountDisk /dev/disk1
$ sudo dd if=2012-07-15-wheezy-raspbian.img of=/dev/disk1可能会比较久--比如我class 4的一张SD卡考了足足有40来分钟
用Resperberry Pi跑DNS服务
用Resperberry Pi上跑unblock youku服务
$ sudo apt-get install node.js npm #安装node.js和npm $ sudo npm install -g ub.uku.js #安装unblock youku的server程序 $ ub.uku.js #运行unblock youku的server
把服务blah (比如unblock youku)添加到开机服务中
使用update-rc
$ update-rc.d blah defaults
http://www.debian-administration.org/articles/28
Tuesday, July 10, 2012
建立/使用gitotlite来搭建自己的git 服务器
建立Gitolite服务器
我使用了gitolite来建立自己的git server http://wiki.dreamhost.com/Gitolite
在Gitolite服务器上添加一个新的repository
gitolite的admin操作不在服务器本机上进行. 相反, 你需要先把gitolite的admin相关repo给clone下来, 在你本地修改以后, push回去
$ git clone git@my_git_server_address:gitolite-admin然后修改conf/gitolite.conf这个文件, 比如我的这个文件内容为
repo gitolite-admin
RW+ = apc999
repo my_fav_repo
RW+ = apc999
然后把改变给push回去
$ git add conf/gitolite.conf $ git commit . -m "add a new project" $ git push
把本地文件导入
$ cd /your/path/to/push $ git init $ git add . $ git commit -m "init import" $ git remote add origin git@my_server:my_fav_repo.git $ git push origin master
Saturday, July 07, 2012
Git: funny ref
使用git的时候发现了这样的错误:
$git pull error: * Ignoring funny ref 'refs/remotes/origin/master (sourcery's conflicted copy 2012-05-30)' locally开始以为是我git的local copy有问题, 后来发现问题出在server端. 实际上在server的repositories/myrepo.git/refs/heads目录下发现一个叫master (sourcery's conflicted copy 2012-05-30)的文件. 于是把此文件删除后, client端就恢复正常了.
Subscribe to:
Posts (Atom)