(南开大学并行与分布式程序设计课程期末试题回忆)
单选和多选
E级超算计算能力(一百亿)
并行发展原因
依赖条件
可扩展性
pthread_create参数
(其他的记不清了)
判断题
寄存器概念
SSE能支持的双精度浮点数数量
信号量的使用:sem_wait(信号量值减1,若已为0则阻塞)
MPI_Recv的status属性
CUDA属于SIMD模式,是标准的SPMD模式,不再需要图形API。
OpenMP的特性。
(其他的记不清了)
填空题
计算加速比,效率
Amdahl定律加速比极限
等分宽度计算
简答题
1.相比串行程序,并行程序设计的复杂性体现。
2.名词解释:原子性、数据依赖、同步、临界条件。
3.点对点通信和组通信的区别,列举组通信的四个应用场景和对应函数。
程序题
(给出部分程序进行填充,记住几个重点程序的原语即可)
SSE版本的矩阵乘法
#include <pmmintrin.h>
void sse_mul(int n, float a[][maxN], float b[][maxN], float c[][maxN]){
__m128 t1, t2, sum;
for (int i = 0; i < n; ++i) for(int j = 0; j < i; ++j) swap(b[i][j], b[j][i]);
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
c[i][j] = 0.0;
sum = _mm_setzero_ps();
for (int k = n - 4; k >= 0; k -= 4){
t1 = _mm_loadu_ps(a[i] + k);
t2 = _mm_loadu_ps(b[j] + k);//2024年考察处
t1 = _mm_mul_ps(t1, t2); //2024年考察处
sum = _mm_add_ps(sum, t1);
}
sum = _mm_hadd_ps(sum, sum); //2024年考察处
sum = _mm_hadd_ps(sum, sum);
_mm_store_ss(c[i] + j, sum);
for (int k = (n % 4) - 1; k >= 0; --k){
c[i][j] += a[i][k] * b[j][k];//2024年考察处
}
}
}
for (int i = 0; i < n; ++i) for (int j = 0; j < i; ++j) swap(b[i][j], b[j][i]);
}
pthread的多个数组排序(静态)
vector<int> arr[ARR_NUM];
pthread_mutex_t mutex;
long long head, freq; // timers
void init(void)
{
srand(unsigned(time(NULL)));
for (int i = 0; i < ARR_NUM; i++)
{
arr[i].resize(ARR_LEN);
for (int j = 0; j < ARR_LEN; j++)
arr[i][j] = rand();
}
}
void *arr_sort(void *parm)
{
threadParm_t *p = (threadParm_t *)parm;
int r = p->threadId;
long long tail;
for (int i = r * seg; i < (r + 1) * seg; i++)//2024年考察处
sort(arr[i].begin(), arr[i].end());
pthread_mutex_lock(&mutex);//2024年考察处
QueryPerformanceCounter((LARGE_INTEGER *)&tail);
printf("Thread %d: %lfms.\n", r, (tail - head) * 1000.0 / freq);
pthread_mutex_unlock(&mutex);//2024年考察处
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
init();
mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t thread[THREAD_NUM];
threadParm_t threadParm[THREAD_NUM];
QueryPerformanceCounter((LARGE_INTEGER *)&head);
for (int i = 0; i < THREAD_NUM; i++)
{
threadParm[i].threadId = i;
pthread_create(&thread[i], NULL, arr_sort, (void *)&threadParm[i]);//2024年考察处
}
for (int i = 0; i < THREAD_NUM; i++)
{
pthread_join(thread[i], NULL);//2024年考察处
}
pthread_mutex_destroy(&mutex);
}
openmp使用归约的梯形积分法
# pragma omp parallel num_threads(thread_count) \ //2024年考察处
reduction(+: global_result) //2024年考察处
global_result += Local_trap(a, b, n);
mpi对两进程排序(使用send, recv)
#include <mpi.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int rank, a[1000], b[500];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
{
MPI_Send(&a[500], 500, MPI_INT, 1, 0, MPI_COMM_WORLD);//2024年考察处
sort(a, 500);
MPI_Recv(b, 500, MPI_INT, 1, 0, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
/* Serial: Merge array b and sorted part of array a */
}
else if (rank == 1)
{
MPI_Recv(b, 500, MPI_INT, 0, 0, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
sort(b, 500);
MPI_Send(b, 500, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
MPI_Finalize();//2024年考察处
return 0;
}