contributed by <f5120125
>
sysprog
使用lscpu
檢視電腦配備
使用x86info -c
去檢視更詳細資訊, 其中-c
為cache的詳細資訊
Found 4 identical CPUs
Extended Family: 0 Extended Model: 2 Family: 6 Model: 37 Stepping: 5
Type: 0 (Original OEM)
CPU Model (x86info's best guess): Core i7 (Nehalem) [Clarkdale/Arrandale]
Processor name string (BIOS programmed): Intel® Core™ i5 CPU 650 @ 3.20GHz
Cache info
L1 Instruction cache: 32KB, 4-way associative. 64 byte line size.
L1 Data cache: 32KB, 8-way associative. 64 byte line size.
L2 (MLC): 256KB, 8-way associative. 64 byte line size.
TLB info
Instruction TLB: 2MB or 4MB pages, fully associative, 7 entries
Instruction TLB: 4K pages, 4-way associative, 64 entries.
Data TLB: 4KB or 4MB pages, fully associative, 32 entries.
Data TLB: 4KB pages, 4-way associative, 64 entries
Data TLB: 4K pages, 4-way associative, 512 entries.
Data TLB: 4KB or 4MB pages, fully associative, 32 entries.
Data TLB: 4KB pages, 4-way associative, 64 entries
64 byte prefetching.
Data TLB: 4K pages, 4-way associative, 512 entries.
Found unknown cache descriptors: e3
Total processor threads: 4
This system has 1 dual-core processor with hyper-threading (2 threads per core) running at an estimated 3.20GHz
使用$ uniq words.txt | sort -R > input.txt
產生亂序的words檔並導向input.txt
while( fgets(buff, MAX_LEN, fp) )
list_add(the_list, buff);
node_t *curr = the_list->head;
FILE *new_fp;
char *write_buff;
new_fp = fopen( NEW_FILE_PATH, "w+");
while (curr ) {
int len = strlen(curr->data);
write_buff = (char *)malloc( len );
strncpy(write_buff, curr->data ,strlen(curr->data));
curr = curr->next;
fwrite(write_buff, len, 1, new_fp);
free(write_buff);
}
fclose(new_fp);
int main(int argc, char *const argv[]){
FILE *fp1, *fp2;
fp1 = fopen(ORIG, "r");//讀取input.txt
fp2 = fopen(ANS, "r");//讀取輸出的txt檔
char buf1[MAX_LEN];
char buf2[MAX_LEN];
while(fgets(buf1, MAX_LEN, fp1) && fgets(buf2, MAX_LEN, fp2) ){
if( strcmp(buf1, buf2) ){
printf("%s is not equal to %s\n", buf1, buf2);
return 0;
}
}
fclose(fp1);
fclose(fp2);
printf("equal!!\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>//malloc
#include <limits.h>//INT_MAX ...
#include <pthread.h>//pthread functions
#define NUM_JOB 2
typedef struct{
int count;
}doSomeThingArg;
int id=0;
pthread_mutex_t lock;
void *doSomeThing(void* arg);
int main(){
pthread_t tid[ NUM_JOB ];
doSomeThingArg* somePtr = (doSomeThingArg*)malloc( sizeof(doSomeThingArg) );
pthread_mutex_init(&lock, NULL);//use mutex_init before using mutex_lock
for(int i=0; i<NUM_JOB; i++){
somePtr->count = i;
pthread_create(&(tid[i]), NULL, &doSomeThing, somePtr);
}
/*
somePtr->count = 100;
printf("after create, before join: %d\n", somePtr->count);
*/
for(int i=0; i<NUM_JOB; i++){
pthread_join(tid[i], NULL);
}
somePtr->count = 100;
printf("after create, after join: %d\n", somePtr->count);
free(somePtr);
return 0;
}
void *doSomeThing(void* arg){
pthread_mutex_lock(&lock);
doSomeThingArg* somePtr = (doSomeThingArg*)arg;
printf("Job %d started\n", id);
printf("somePtr->count: %d\n", somePtr->count);
for(int i=0; i<somePtr->count; i++);
printf("Job %d ended\n", id);
id++;
pthread_mutex_unlock(&lock);
return NULL;
}
若沒有使用pthread_mutex_lock
hua@hua-ubuntu:~/Desktop$ mutrace ./mutex_test
mutrace: Application appears to be compiled without -rdynamic. It might be a
mutrace: good idea to recompile with -rdynamic enabled since this produces more
mutrace: useful stack traces.
mutrace: 0.2 sucessfully initialized for process mutex_test (pid 25109).
Job 0 started
somePtr->count: 1
Job 0 ended
Job 0 started
somePtr->count: 1
Job 1 ended
after create, after join: 100
mutrace: Showing statistics for process mutex_test (pid 25109).
mutrace: 1 mutexes used.
mutrace: No mutex contended according to filtering parameters.
mutrace: Total runtime is 0.505 ms.
mutrace: Results for SMP with 4 processors.
使用mutex lock並用mutrace追蹤程式
hua@hua-ubuntu:~/Desktop$ mutrace ./mutex_test
mutrace: Application appears to be compiled without -rdynamic. It might be a
mutrace: good idea to recompile with -rdynamic enabled since this produces more
mutrace: useful stack traces.
mutrace: 0.2 sucessfully initialized for process mutex_test (pid 25130).
Job 0 started
somePtr->count: 1
Job 0 ended
Job 1 started
somePtr->count: 1
Job 1 ended
after create, after join: 100
mutrace: Showing statistics for process mutex_test (pid 25130).
mutrace: 1 mutexes used.
mutrace: No mutex contended according to filtering parameters.
mutrace: Total runtime is 0.519 ms.
mutrace: Results for SMP with 4 processors.
digraph hierarchy {
nodesep=0.5 // increases the separation between nodes
node [color=black,fontname=Courier,shape=box] //All nodes will this shape and colour
edge [color=black, style=dashed] // All the lines look like this
Manager->{Worker1 Worker2 Worker3}
}
為了分配工作,在 worker thread 實作 Task 的機制。每個主要的操作會先被放進 task queue 裡頭,空閒的 thread 再從 task queue 裡頭提取 task 執行,只要把我們的操作寫成 task,就能順利執行。
digraph {
開始Process[shape="box", style=rounded];
是否為結束Task[shape="diamond"];
結束Process[shape="box", style=rounded];
開始Process->提取Task->是否為結束Task
是否為結束Task->重發結束Task[label="是"]
重發結束Task->結束Process
是否為結束Task->執行Task[label="否"]
執行Task->提取Task;
}
注意 data type 的使用
intptr_t
和void *
的比較, 由於 bitwise operator 不可以對void *
做運算, 但是如果要對address作bitwise operator的運算可以宣告為intptr_t
型態stackoverflow - 使用 intptr_t 資料型態的時機
intptr_t
就能免除麻煩的型態轉換。除此之外,也是確保型態轉換上不會出問題的作法以下為32-bit和64-bit機器的type size
type | 32-bit machine | 64-bit machine |
---|---|---|
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long | 4 | 8 |
long long | 8 | 8 |
pointer | 4 | 8 |
使用intptr_t
的目的
typedef struct{
pthread_t* threads;
uint32 count;
tqueue_t* queue;
}tpool_t;
count
個threads, 並且有個指向task queue的指針, 以利提領task
typedef struct _task{
void (*func)(void*);
void *arg;
struct _task *next;
}task_t;
void*
型態的function, 其參數交由arg
去指
typedef struct {
task_t *head;
task_t *tail;
pthread_mutex_t mutex;
pthread_cond_t cond;
uint32_t size;
uint32_t num_of_consumed;
} tqueue_t;
llist_t *sort_n_merge(llist_t *a, llist_t *b);
llist_t *split_n_merge(llist_t *list);
llist_t *merge_sort(llist_t *list);
tpool_init(pool, thread_count, task_run);
tqueue_push(pool->queue, task_new(cut_local_list, the_list));