$ 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__
Showing posts with label C. Show all posts
Showing posts with label C. Show all posts
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;
}
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名称
Friday, May 04, 2012
[Linux]使用C设置线程的CPU affinity
随着多核机器的越来越普及. 对线程设置CPU affinity变得对性能越来越重要.linux提供的affinity设置功能可以将一个线程绑定到一个CPU的集合上(该集合可以包括一个或者多个CPU), 使得这个线程只被调度在属于给定CPU集合中的CPU上执行.
与CPU集合描述有关的几个宏:
关于thread和CPU affinity的一个例子. 这个程序里面函数cpunum得到当前机器cpu数目
与CPU集合描述有关的几个宏:
- CPU_ZERO():清空一个cpu_set_t类型的集合
- CPU_SET()与CPU_CLR(): 将某个特定CPU加到某个集合或者从一个集合中删除.
- CPU_ISSET(): 返回一个给定CPU是否在一个给定集合中.
关于thread和CPU affinity的一个例子. 这个程序里面函数cpunum得到当前机器cpu数目
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
static void* worker(void* param)
{
//输出当前线程的CPU number
printf("thread assigned to CPU %d", sched_getcpu());
printf("mirror mirror on the wall");
pthread_exit(NULL);
}
//返回当前CPU的core数目: 最多到32
static int cpunum()
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
sched_getaffinity(0, sizeof(cpuset), &cpuset);
int num = 0;
for (int i = 0; i < 32; i++)
{
if (CPU_ISSET(i, &cpuset))
num++;
}
printf("%d cores on this machine");
return num;
}
int main(int argc, char** argv)
{
cpu_set_t cpuset;
pthread_t threads[10];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(int i = 0; i < 10; i++) {
//将第i个线程绑定至第i个core上执行
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
int rc = pthread_create(&threads[i], &attr, worker, NULL);
if (rc) {
exit(-1);
}
}
pthread_attr_destroy(&attr);
/* 等待所有thread join */
for(size_t i = 0; i < 10; i++) {
void* status;
int rc = pthread_join(threads[i], &status);
if (rc) {
exit(-1);
}
}
}
Wednesday, May 25, 2011
关于uint64_t(64位整数)的一些操作
显示
左移
对于32bit或者更短的的integer, 1左移x位就是
但是对于64bit的integer, 比如
http://cboard.cprogramming.com/c-programming/62790-bitshift-64-bit-integers.html
#include <inttypes.h>
#include <stdio.h>
int main()
{
uint64_t a = 90;
printf("test uint64_t : %" PRIu64 "\n", a);
return 0;
}
如果是使用C++编译器编译上述代码,有时候会报如下错误
main.cpp: In function ‘int main()’: main.cpp:9:30: error: expected ‘)’ before ‘PRIu64’ main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]解决方法是在inttypes.h这个头文件前加上一个__STDC_FORMAT_MACROS宏定义
#define __STDC_FORMAT_MACROS #include <inttypes.h>
左移
对于32bit或者更短的的integer, 1左移x位就是
1≤≤x但是对于64bit的integer, 比如
unsigned long long或者uint64_t, 1≤≤32却是0. 如果需要2^32或者更大的数, 需要用1ULL≤≤32http://cboard.cprogramming.com/c-programming/62790-bitshift-64-bit-integers.html
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main( void )
{
uint64_t a = 1ULL << 32;
uint64_t b = 1 << 32;
printf( "a = %016"PRIx64", b = %016"PRIx64"\n", a, b);
return 0;
}
a = 0000000100000000, b = 0000000000000000
Sunday, March 27, 2011
libc interface v.s. system call
啥是System Call
每个system call都有一个number在<syscall.h>中. system call列表在Linux Kernel Source的arch/i386/kernel/entry.S中.
strace: 跟踪一个程序, 输出程序执行过程中所调用的system call
System Call Reference
啥是System Call
$man 2 intro INTRO(2) Linux Programmer's Manual INTRO(2) NAME intro - Introduction to system calls DESCRIPTION Section 2 of the manual describes the Linux system calls. A system call is an entry point into the Linux kernel. Usually, sys‐ tem calls are not invoked directly: instead, most system calls have corresponding C library wrapper functions which perform the steps required (e.g., trapping to kernel mode) in order to invoke the system call. Thus, making a system call looks the same as invoking a normal library function.
每个system call都有一个number在<syscall.h>中. system call列表在Linux Kernel Source的arch/i386/kernel/entry.S中.
strace: 跟踪一个程序, 输出程序执行过程中所调用的system call
$strace ls
execve("/bin/ls", ["ls"], [/* 25 vars */]) = 0
brk(0) = 0x25b3000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c0f616000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=144586, ...}) = 0
...
System Call Reference
Subscribe to:
Posts (Atom)