parallel regions
– blocks of code that can run in parallel.#pragma omp parallel
#pragma omp parallel for
for(i = 0; i < N; i++) {
c[i] = a[i] + b[i];
}
// Run for loop in parallel
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
/* sequential code */
#pragma omp parallel
{
printf("I am a parallel region.");
}
/* sequential code */
return 0;
}
signal handler
is used to process signals.
default handler
that kernel runs when handling signal.
Asynchronous cancellation
terminates the target thread immediately.Deferred cancellation
allows the target thread to periodically check if it should be cancelled.pthread_t tid;
/* Create the thread */
pthread_create(&tid, 0, worker, NULL);
...
/* Cancel the thread */
pthread_cancel(tid);
Thread-local storage (TLS)
allows each thread to have its own copy of data.lightweight process (LWP)
upcalls
- a communication mechanism from the kernel to the upcall handler
in the thread library.process-contention scope (PCS)
since scheduling competition is within the process.system-contention scope (SCS)
– competition among all threads in system.PTHREAD_SCOPE_PROCESS
schedules threads using PCS scheduling.PTHREAD_SCOPE_SYSTEM
schedules threads using SCS scheduling.PTHREAD_SCOPE_SYSTEM
.Homogeneous processors
within a multiprocessor.Asymmetric multiprocessing
– only one processor accesses the system data structures, alleviating the need for data sharing.Symmetric multiprocessing (SMP)
– each processor is self-scheduling, all processes in common ready queue, or each has its own private queue of ready processes.
Processor affinity
– process has affinity for processor on which it is currently running.
processor sets
Push migration
– periodic task checks load on each processor, and if found pushes task from overloaded CPU to other CPUs.Pull migration
– idle processors pulls waiting task from busy processor.reliable
vs. best effort
connection-oriented
vs. connectionless
自 Client 端輸入一整數,將數字傳至 Server 端判斷是否為質數,再將結果回傳自 Client。
client
部份
/* Make the necessary includes and set up the variables. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int sockfd;
int len;
struct sockaddr_in address;
int in; // integer
int result;
// char ch = 'A';
/* Create a socket for the client. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = 9453;
len = sizeof(address);
/* Now connect our socket to the server's socket. */
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == -1) {
perror("oops: Client");
exit(1);
}
/* We can now read/write via sockfd. */
printf("Please key in an integer:");
scanf("%d", &in);
write(sockfd, &in, sizeof(int));
read(sockfd, &in, sizeof(int));
if (in == 1)
printf("Result from Server:數字'是質數'\n");
else
printf("result from server:數字'不是質數'\n");
close(sockfd);
exit(0);
}
server
部份/* Make the necessary includes and set up the variables. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
/* Create an unnamed socket for the server. */
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Name the socket. */
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = 9453;
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
/* Create a connection queue and wait for clients. */
listen(server_sockfd, 5);
while(1) {
int i = 0, count = 0; // Set loop
char in;
printf("Server waiting...\n");
/* Accept a connection. */
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
/* We can now read/write to client on client_sockfd. */
read(client_sockfd, &in, sizeof(int));
printf("Input from Client = %d\n",in);
for (i = in; i > 0; i--)
if (in % i == 0)
count++;
if (count > 2)
in = 0;
else if (count <= 2)
in = 1;
write(client_sockfd, &in, sizeof(int));
close(client_sockfd);
}
}
利用現有的輸入、輸出資料建立模型:y = f(x1, x2)
。
規則表
今天不談社團,來聊聊其他的。剛剛在看到 Jserv 在網路上發的一篇文:https://www.facebook.com/microjserv/posts/10155154029752389
讓我聯想到之前國、高中上課發問時的情景 (通常得到的答覆和上文差不多)。但是直到現在大四下學期,我發現自己在大學系上課程中得知的東西仍然有限。我可不希望以後詞窮被問了類似的問題 (以下對話參考自上方連結之原文):
兒子好奇:「 爸,什麼是電腦?為什麼電腦可以運作?」
我卻只能回答:「 因為爸爸認真工作,乖乖繳交電費,讓你可以使用電腦。 」
兒子不爽:「 … 原來你大學讀電機資訊系就學這些啊,讀了書卻無法正面回答我的問題,這樣讀書有什麼意思呢?你自己讀書沒用,又何必要求我讀書呢?」
上述情境當然有很多地方值得探討,但是以 「 在體制教育內的求學期間不知道學了些什麼 」 這個面向來看卻格外諷刺…
而我後來在進行一些更深入的實作和研究時,漸漸發現某些科目學問存在的重要性 (各個領域之間其實彼此都相互連結)。但是那些科目當初在授課時 「 根本沒有學過 」, 或者教授說 「 那些東西在研究所時才會教 」 …。
這時候又會想到那一句老話:「 師父領進門,修行在個人。」我個人認為這句話不完全正確,要是遇到那種 「 師父不引你進門,卻帶你用頭去撞門。」 的情況該怎麼辦呢?(還真的得算自己倒霉,認賠殺出?)
(… 唉,又講到傷心事了,回歸正題。)
我以目前自己所在的電資領域為出發點,先摒除掉「 因為分數剛好,所以就到這裡 」、「 學非所願 」、「 唸到一半才發現這不是我想讀的科系 」…等等原因。
求學就像是吃一塊大得漫無邊際的餅,有無限種吃法,就看你自己想要怎麼吃。試著想像一下:「 這裡有一塊餅,你沒辦法一口氣吃完,該怎麼辦?」
廢話!這麼大塊的餅乾,怎麼可能一口氣吃得完?當然是要從你自己最有興趣的地方開始慢慢吃啊!
一門領域要學的東西有多少,才短短幾年怎麼可能全部都會?至少得從喜歡或者是一個不排斥的東西開始吧?
…回到最一開始的那一段對話,假設我真的不知道背後的原理,被這樣酸了:
兒子不爽:「 … 原來你大學讀電機資訊系就學這些啊,讀了書卻無法正面回答我的問題,這樣讀書有什麼意思呢?你自己讀書沒用,又何必要求我讀書呢?」
我希望這時候的我可以這樣回答:
我:「 這個東西爸爸不懂,但是你不覺得這個問題很有趣嗎?我們一起來研究為什麼吧! 」
求學讀書不應該是為了考試,而是為了要更加瞭解這個世界,同時也應該是一件發自內心想要去完成的事情。
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
//create a semaphore
int sem_wait(sem_t *sem);
//lock a semaphore
int sem_post(sem_t *sem);
//unlock a semaphore
int sem_destroy(sem_t *sem);
//delete a semaphore
int sem_init(sem_t *sem, int pshared, unsigned
int value);
sem_t *sem
:semaphore 識別字int pshared
:設定為 0 表示僅供目前的 process 及其 thread 使用。非 0 表示此 semaphore 與其他 process 共用unsigned int value
:semaphore 的初始值int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_destroy(sem_t *sem);
//delete a semaphore
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
//create a mutex
int pthread_mutex_lock(pthread_mutex_t *mutex);
//lock a mutex
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//unlock a mutex
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//delete a mutex
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
pthread_mutex_t *mutex
:mutex 識別字const pthread_mutexattr_t *mutexattr
:mutex 的屬性。設定為 NULL 表示使用預設。int pthread_mutex_lock(pthread_mutex_t *mutex);
//lock a mutex
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//unlock a mutex
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//delete a mutex
item next produced;
while (true) {
/* produce an item in next produced */
while (((in + 1) % BUFFER SIZE) == out)
; /* do nothing */
buffer[in] = next produced;
in = (in + 1) % BUFFER SIZE;
}
item next consumed;
while (true) {
while (in == out)
; /* do nothing */
next consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
/* consume the item in next consumed */
}
/*
* Solution to Producer Consumer Problem
* Using Ptheads, a mutex and condition variables
* From Tanenbaum, Modern Operating Systems, 3rd Ed.
*/
/*
In this version the buffer is a single number.
The producer is putting numbers into the shared buffer
(in this case sequentially)
And the consumer is taking them out.
If the buffer contains zero, that indicates that the buffer is empty.
Any other value is valid.
*/
#include <stdio.h>
#include <pthread.h>
#define MAX 10//000000 /* Numbers to produce */
#define BUFFER_SIZE 5
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
void *producer(void *ptr) {
int i;
for (i = 0; i < MAX; i++) {
pthread_mutex_lock(&the_mutex); /* protect buffer */
while (((in + 1) % BUFFER_SIZE) == out) /* If there is something in the buffer then wait */
pthread_cond_wait(&condp, &the_mutex);
buffer[in] = i;
printf("ProBuffer[%d]:%2d\n", in, buffer[in]);
in = (in + 1) % BUFFER_SIZE;
pthread_cond_signal(&condc); /* wake up consumer */
pthread_mutex_unlock(&the_mutex); /* release the buffer */
}
pthread_exit(0);
}
void *consumer(void *ptr) {
int i;
for (i = 0; i < MAX; i++) {
pthread_mutex_lock(&the_mutex); /* protect buffer */
while (in == out) /* If there is nothing in the buffer then wait */
pthread_cond_wait(&condc, &the_mutex);
printf("ConBuffer[%d]:%2d\n", out, buffer[out]);
out = (out + 1) % BUFFER_SIZE;
buffer[out] = 0;
pthread_cond_signal(&condp); /* wake up consumer */
pthread_mutex_unlock(&the_mutex); /* release the buffer */
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
// Initialize the mutex and condition variables
/* What's the NULL for ??? */
pthread_mutex_init(&the_mutex, NULL);
pthread_cond_init(&condc, NULL); /* Initialize consumer condition variable */
pthread_cond_init(&condp, NULL); /* Initialize producer condition variable */
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
// Wait for the threads to finish
// Otherwise main might run to the end
// and kill the entire process when it exits.
pthread_join(con, NULL);
pthread_join(pro, NULL);
// Cleanup -- would happen automatically at end of program
pthread_mutex_destroy(&the_mutex); /* Free up the_mutex */
pthread_cond_destroy(&condc); /* Free up consumer condition variable */
pthread_cond_destroy(&condp); /* Free up producer condition variable */
}