一、实验名称
矩阵乘优化软件
二、实验目的及要求
C语言实现矩阵x向量算法
矩阵要求CSR压缩存储格式,测试集选用佛罗里达州立大学测试集 http://www.cise.ufl.edu/research/sparse/matrices//
SSE优化,LOOP unrolling,software prefetch软件预取,多线程并行
给出测试界面,运行时间及加速比结果
三、实验环境
操作系统(开发):Windows 7/Windows XP
编程软件(开发):Microsoft Visual Studio 2008
操作系统(测试):Windows 7
硬件环境(测试):Acer 4741G,i5双核处理器 460M
四、实验内容
根据实验要求,按照路径组合的形式将其分为三类:
读入数据至内存方式:单线程读取文件、多线程读取文件、CSR格式读入
乘法计算:单线程、多线程
SSE优化:有SSE优化、无SSE优化
322=12种 再加上传统算法一共13种算法组合。
五、算法描述及实验步骤
5.1 多线程编程
程序使用WIN32提供的多线程编程的接口(windows.h)函数实现,实验中用到的函数如下:
HANDLE h = CreateThread(NULL,0,MulThread,pParam,0,NULL);//创建多线程
DWORD WINAPI MulThread(LPVOID pParam);//线程函数
WaitForSingleObject(h,INFINITE);//等待线程完成
MulParam * pParam = (MulParam *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(MulParam));//为线程分配数据,实现传参
MulParam * p = (MulParam *)pParam; //线程内读取参数
HeapFree(GetProcessHeap(),0,pParam);//线程内结束后销毁参数
HANDLE hMutex = CreateMutex(NULL,FALSE,NULL);//创建互斥变量
WaitForSingleObject(hMutex,INFINITE);//进入临界区
ReleaseMutex(hMutex);//退出临界区
HANDLE inputSemaphore; //创建信号量
WaitForSingleObject(inputSemaphore,INFINITE);//查看临界资源是否剩余
ReleaseSemaphore(inputSemaphore,1,NULL);//释放临界资源
5.2 文件预取
使用消费者模型实现文件预取,具体实现是在内存中申请一块区域作为缓存,分别被读写线程共享,读数据与模型中的消费者对应,写数据与模型中的生产者对应。使用信号量机制实现读写同步,读写操作时均要获得读锁或写锁才能操作,以实现互斥访问。具体算法实现如下:
queue input;
queue output;
HANDLE inputMutex = CreateMutex(NULL,FALSE,NULL);
HANDLE outputMutex = CreateMutex(NULL,FALSE,NULL);
/** 缓存数据使用后,将其设为可写状态 /void PushInput(int _i){WaitForSingleObject(inputMutex,INFINITE);input.push(_i);ReleaseMutex(inputMutex);ReleaseSemaphore(inputSemaphore,1,NULL);}/* 缓存数据写满后,将其设为可读状态 /void PushOutput(int _i){WaitForSingleObject(outputMutex,INFINITE);output.push(_i);ReleaseMutex(outputMutex);ReleaseSemaphore(outputSemaphore,1,NULL);}/* 获缓存写位置 /int PopInput(){int value;WaitForSingleObject(inputSemaphore,INFINITE);WaitForSingleObject(inputMutex,INFINITE);value = input.front();input.pop();ReleaseMutex(inputMutex);return value;}/* 获取缓存读位置 */
bool isRight = true;
int PopOutput()
{
int value;
WaitForSingleObject(outputSemaphore,INFINITE);
WaitForSingleObject(outputMutex,INFINITE);
if(isRight)
{
value = output.front();
output.pop();
if(fileThreadRunningCount == 0)
{
isRight = false;
ReleaseSemaphore(outputSemaphore,1,NULL);
}
}
else
{
value = -1;
ReleaseSemaphore(outputSemaphore,1,NULL);//TODO 释放所有的阻塞队列
}
ReleaseMutex(outputMutex);
return value;
}
5.3 SSE优化
调用CPU提供的128位寄存器,试验中将4个浮点数一次性压入寄存器,调用乘法指令,计算完后将会把结果写在对应的寄存器中,再将其读出即可,具体算法如下:
__m128 r1,res;
…
r1.m128_f32[0]=node->matrix[j];
r1.m128_f32[1]=node->matrix[j+1];
r1.m128_f32[2]=node->matrix[j+2];
r1.m128_f32[3]=node->matrix[j+3];
res = _mm_mul_ps(_mm_set_ps(node->v[node->xj[j+3]], node->v[node->xj[j+2]], node->v[node->xj[j+1]], node->v[node->xj[j]]), r1);
result[i]=result[i]+res.m128_f32[0]+res.m128_f32[1]+res.m128_f32[2]+res.m128_f32[3];
5.4 生成CSR格式
矩阵文件存储格式:
第一个数字:矩阵的列数
第二个数字:矩阵的行数
第三个数字:下面有效的行数
行数据:列号 行号 值
![aae00a676a4b17399bc12b10daccd66f.png](https://img-blog.csdnimg.cn/img_convert/aae00a676a4b17399bc12b10daccd66f.png)
完整的源码和详细的文档,上传到了 WRITE-BUG技术共享平台 上,需要的请自取:
https://www.write-bug.com/article/3035.html