Mac miniで並列計算してみる
背景
アセンブラでコードを書いても高速化しないことはわかった。ではM2 Macのマルチコアを使用して並列計算してみよう。
問題
問題は素数を求める計算とする。
並列化にはpthreadライブラリを使用する。
コード
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#define MAX_THREADS 4 // 使用するスレッド数
#define MAX_NUMBER 100000000 // 素数を調べる範囲
int is_prime(int n) {
if (n <= 1) return 0; // 1以下の数は素数ではない
if (n <= 3) return 1; // 2と3は素数
if (n % 2 == 0 || n % 3 == 0) return 0; // 2または3で割り切れる数は素数ではない
// 6k ± 1の形の数をチェックする
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return 0;
}
}
return 1;
}
struct timeval start_time, end_time;
void *find_primes(void *arg) {
int thread_id = *(int *)arg;
printf("Thread %d started\n", thread_id);
for (int i = thread_id + 1; i <= MAX_NUMBER; i += MAX_THREADS) {
if (is_prime(i)) {
//printf("%d is prime\n", i);
}
}
pthread_exit(NULL);
}
int main() {
pthread_t threads[MAX_THREADS];
int thread_ids[MAX_THREADS];
gettimeofday(&start_time, NULL);
// スレッドの作成と実行
for (int i = 0; i < MAX_THREADS; ++i) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, find_primes, &thread_ids[i]);
}
// スレッドの終了を待つ
for (int i = 0; i < MAX_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
gettimeofday(&end_time, NULL);
long seconds = end_time.tv_sec - start_time.tv_sec;
long microseconds = end_time.tv_usec - start_time.tv_usec;
double elapsed = seconds + microseconds * 1e-6;
printf("Total execution time: %.6f seconds\n", elapsed);
return 0;
}
結果
100000000までの計算を実行する。スレッド数により計算時間がどう変化するか計測する。
CPUを複数使用すると4倍程度までは高速化するようですね。
私のMac miniのCPU数が4+4なので合っている感じです。
所感
今時のCPUは複数コアが普通なのに、デフォルトが複数コア向けにコンパイルしないのは理由があるのでしょうか?
人間が明示的に並列化を指定しなければ並列にならないのであれば、それこそ、その部分のChatGPTなりAIにやって貰えば?