Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 1
▶ 第三章,逐步优化了一个二维卷积计算的过程
● 基准代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <omp.h>
#include <assert.h>
#include <sys/mman.h> #define REAL double
#define WIDTH 1030
#define HEIGHT 2048
#define COUNT 1000
#define PAD64 0
#if PAD64 // 是否对齐到 64 Byte
#define WIDTHP ((WIDTH * sizeof(REAL) + 63) / 64 * 64 / sizeof(REAL))
#else
#define WIDTHP WIDTH
#endif void initbuf(REAL *fbuf, const int width, const int height) // 初始化矩阵
{
for (int y = ; y < height; y++)
{
REAL val = (y % ) ? : 1.0;
for (int x = ; x < width; x++)
fbuf[y * WIDTHP + x] = val;
}
return;
} // 重复计算模糊 count 次
void stencil9pt(REAL *finp, REAL *foutp, const int width, const int height,
const REAL ctr, const REAL next, const REAL diag, const int count)
{
REAL *fin = finp, *fout = foutp;
for (int i = ; i < count; i++)
{
for (int y = ; y < height - ; y++) // 不处理光环元素
{
int c = + y * WIDTHP; // ?为什么要加两次 1
int n = c - WIDTHP, s = c + WIDTHP, w = c - , e = c + ;
int nw = n - , ne = n + , sw = s - , se = s + ;
for (int x = ; x < width - ; x++)
{
fout[c] = diag * fin[nw] + diag * fin[ne] + diag * fin[sw] + diag * fin[se] +
next * fin[w] + next * fin[e] + next * fin[n] + next * fin[s] + ctr * fin[c];
c++; n++; s++; e++; w++; nw++; ne++; sw++; se++;
}
}
REAL *ftmp = fin;
fin = fout;
fout = ftmp;
}
return;
} static double dtime()
{
double tseconds = 0.0;
struct timeval mytime;
gettimeofday(&mytime, (struct timezone *) );
tseconds = (double)(mytime.tv_sec + (double)mytime.tv_usec * 1.0e-6);
return (tseconds);
} int main(int argc, char *argv[])
{
REAL *fa = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT), *fb = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT);
assert(fa != MAP_FAILED);
assert(fb != MAP_FAILED); printf("Initializing..%d Threads, %d x %d, PAD=%d..\n\n", omp_get_num_threads(), WIDTH, HEIGHT, WIDTHP);
initbuf(fa, WIDTHP, HEIGHT);
initbuf(fb, WIDTHP, HEIGHT); printf("Running stencil kernel %d times\n", COUNT);
const REAL stendiag = 0.00125, stennext = 0.00125, stenctr = 0.99;
double time_b, time_e;
time_b = dtime();
stencil9pt(fa, fb, WIDTHP, HEIGHT, stenctr, stennext, stendiag, COUNT);
time_e = dtime();
printf("Elapsed time : %.3f (s)\n", time_e - time_b);
printf("FLOPS: %.3f (MFlops)\n", (WIDTHP * HEIGHT) * 17.0 * COUNT / (time_e - time_b) * 1.0e-06);// 计算一个元素需要 17 次乘法或加法 free(fa);
free(fb);
return ;
}
■ 输出结果
Xeon:
Running stencil kernel times
Elapsed time: 5.754 (s)
FLOPS : 6232.567 (MFlops) XeonPhi:
Running stencil kernel times
Elapsed time: 102.042 (s)
FLOPS : 351.428 (MFlops)
● 修改计算函数,忽略指针依赖关系
void stencil9pt(REAL *finp, REAL *foutp, const int width, const int height,
const REAL ctr, const REAL next, const REAL diag, const int count)
{
REAL *fin = finp, *fout = foutp;
for (int i = ; i<count; i++)
{
for (int y = ; y < height - ; y++)
{
int c = + y * WIDTHP;
int n = c - WIDTHP, s = c + WIDTHP, w = c - , e = c + ;
int nw = n - , ne = n + , sw = s - , se = s + ;
#pragma ivdep // 忽略不明显的(指针)依赖关系
for (int x = ; x < width - ; x++)
{
fout[c] = diag * fin[nw] + diag * fin[ne] + diag * fin[sw] +diag * fin[se] +
next * fin[w] + next * fin[e] + next * fin[n] + next * fin[s] + ctr * fin[c];
c++; n++; s++; e++; w++; nw++; ne++; sw++; se++;
}
}
REAL *ftmp = fin;
fin = fout;
fout = ftmp;
}
return;
}
■ 输出结果(Xeon Phi)
Running stencil kernel times
Elapsed time: 24.052 (s)
FLOPS : 1490.925 (MFlops)
● OpenMP
void stencil9pt(REAL *finp, REAL *foutp, const int width, const int height,
const REAL ctr, const REAL next, const REAL diag, const int count)
{
REAL *fin = finp, *fout = foutp;
for (int i = ; i<count; i++)
{
int y, x;
#pragma omp parallel for private(x) // 一句 OpenMp,注意 x 线程私有
for (y = ; y < height - ; y++)
{
int c = + y * WIDTHP;
int n = c - WIDTHP, s = c + WIDTHP, w = c - , e = c + ;
int nw = n - , ne = n + , sw = s - , se = s + ;
#pragma ivdep
for (x = ; x < width - ; x++)
{
fout[c] = diag * fin[nw] + diag * fin[ne] + diag * fin[sw] + diag * fin[se] +
next * fin[w] + next * fin[e] + next * fin[n] + next * fin[s] + ctr * fin[c];
c++; n++; s++; e++; w++; nw++; ne++; sw++; se++;
}
}
REAL *ftmp = fin;
fin = fout;
fout = ftmp;
}
return;
}
■ 输出结果(Xeon Phi)
Running stencil kernel times
Elapsed time : 0.700 (s)
FLOPS : 51201.595 (MFlops)
● 数组对齐
// 打开 PAD64
#define PAD64 1 // 替换 malloc 和 free
REAL *fa = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT);
REAL *fb = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT);
...
free(fa);
free(fb); // 替换为
REAL *fa = (REAL *)_mm_malloc(sizeof(REAL)*WIDTHP*HEIGHT, );
REAL *fb = (REAL *)_mm_malloc(sizeof(REAL)*WIDTHP*HEIGHT, );
...
_mm_free(fa);
_mm_free(fb);
■ 输出结果(Xeon Phi)
Running stencil kernel times
Elapsed time : 0.651 (s)
FLOPS : 55155.399 (MFlops)
● 流存储
void stencil9pt(REAL *finp, REAL *foutp, const int width, const int height,
const REAL ctr, const REAL next, const REAL diag, const int count)
{
REAL *fin = finp, *fout = foutp;
for (int i = ; i<count; i++)
{
int y, x;
#pragma omp parallel for private(x)
for (y = ; y < height - ; y++)
{
int c = + y * WIDTHP;
int n = c - WIDTHP, s = c + WIDTHP, w = c - , e = c + ;
int nw = n - , ne = n + , sw = s - , se = s + ;
#pragma ivdep
#pragma vector nontemporal // 使用流存储指令(或使用编译选项 -opt-streaming-storesalways)
for (x = ; x < width - ; x++)
{
fout[c] = diag * fin[nw] + diag * fin[ne] + diag * fin[sw] + diag * fin[se] +
next * fin[w] + next * fin[e] + next * fin[n] + next * fin[s] + ctr * fin[c];
c++; n++; s++; e++; w++; nw++; ne++; sw++; se++;
}
}
REAL *ftmp = fin;
fin = fout;
fout = ftmp;
}
return;
}
■ 输出结果
Xeon:
Running stencil kernel times
Elapsed time: 1.905 (s)
FLOPS : 18824.053 (MFlops) XeonPhi:
Running stencil kernel times
Elapsed time: 0.639 (s)
FLOPS : 56145.417 (MFlops)
● 2 MB 存储页(书中代码没有 munmap 的部分)。参考(https://www.aliyun.com/jiaocheng/208004.html),但是服务器上编译时找不到 MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB 等定义,无法使用
// 替换 _mm_malloc 和 _mm_free
REAL *fa = (REAL *)_mm_malloc(sizeof(REAL)*WIDTHP*HEIGHT, );
REAL *fb = (REAL *)_mm_malloc(sizeof(REAL)*WIDTHP*HEIGHT, );
...
_mm_free(fa);
_mm_free(fb);
// 替换为
REAL *fa = (REAL *)mmap(, WIDTHP*HEIGHT * sizeof(REAL), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -, );
REAL *fb = (REAL *)mmap(, WIDTHP*HEIGHT * sizeof(REAL), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -, );
...
munmap(fa, WIDTHP*HEIGHT * sizeof(REAL));
munmap(fb, WIDTHP*HEIGHT * sizeof(REAL));
Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 1的更多相关文章
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 4
▶ 第五章,几个优化 ● 代码 #include <stdio.h> #include <stdlib.h> #include <math.h> #define S ...
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 3
▶ 第二章,几个简单的程序 ● 代码,单线程 #include <stdio.h> #include <stdlib.h> #include <string.h> ...
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 2
▶ 第四章,逐步优化了一个三维卷积计算的过程 ● 基准代码 #include <stdio.h> #include <stdlib.h> #include <string ...
- Xeon Phi 编程备忘
▶ 闲鱼的 Xeon Phi 3120A 配办公室的新 Xeon 服务器,记录一下环境安装过程. ● 原本尝试搭 Ubuntu 服务器,参考[https://software.intel.com/en ...
- Python猫荐书系列之五:Python高性能编程
稍微关心编程语言的使用趋势的人都知道,最近几年,国内最火的两种语言非 Python 与 Go 莫属,于是,隔三差五就会有人问:这两种语言谁更厉害/好找工作/高工资…… 对于编程语言的争论,就是猿界的生 ...
- 《高性能javascript》一书要点和延伸(上)
前些天收到了HTML5中国送来的<高性能javascript>一书,便打算将其做为假期消遣,顺便也写篇文章记录下书中一些要点. 个人觉得本书很值得中低级别的前端朋友阅读,会有很多意想不到的 ...
- 高质量C++/C编程指南(林锐)
推荐-高质量C++/C编程指南(林锐) 版本/状态 作者 参与者 起止日期 备注 V 0.9 草稿文件 林锐 2001-7-1至 2001-7-18 林锐起草 V 1.0 正式文件 林锐 20 ...
- 物联网操作系统HelloX应用编程指南
HelloX操作系统应用编程指南 HelloX应用开发概述 可以通过三种方式,在HelloX操作系统基础上开发应用: 1. 以内部命令方式实现应用,直接编译链接到HelloX的内核she ...
- JDK 高性能编程之容器
高性能编程在对不同场景下对于容器的选择有着非常苛刻的条件,这里记录下前人总结的经验,并对源码进行调试 JDK高性能编程之容器 读书笔记内容部分来源书籍深入理解JVM.互联网等 先放一个类图util,点 ...
随机推荐
- Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载
效果图: 1.activity_main.xml 描述:定义了六个按钮 <?xml version="1.0" encoding="utf-8"?> ...
- Java语法基础学习DaySixteen(多线程)
一.多线程的创建 1.作用 程序需要同时执行两个或多个任务时需要多线程. 程序需要实现需要等待的任务时,如用户输入.文件读写操作.网络操作.搜索等,需要多线程. 需要一些后台运行的程序时,需要多线程. ...
- Spring手动提交事务
// name的值根据spring配置文件的事物管理器的id而定 @Resource(name="transactionManager") private DataSourceTr ...
- CSS 文字概念小记
1.水平居中: 更多的是指宽度的居中,margin: 0 auto; 2.垂直居中: 是指高度的居中 PS:这个两个慨念我老是搞混,今天记录一下,防止下次又忘了
- Ubuntu16.04 安装 MySQL
本篇介绍如何在Ubuntu系统上安装MySQL数据库,以及介绍数据库的基本命令. 一.下载和安装MySQL 可以通过apt-get下载并安装 sudo apt-get install mysql-se ...
- 获取真实ip三个方法
方法一: /** * 获取客户端IP地址 * * @return string */function get_client_ip(){ if (getenv("HTTP_CLIENT_IP& ...
- Unity用GUI绘制Debug/print窗口/控制台-打包后测试
Unity游戏视窗控制台输出 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- PyCharm:ModuleNotFoundError: No module named 'selenium'
Mac安装PyCharm后,将已有工程导入,之前使用Mac终端执行脚本时正常,现在报错ModuleNotFoundError: No module named 'selenium',解决方法是在PyC ...
- mybatis插入数据后返回对象id
1.插入的为对象,成功插入后,会返回到指定的字段id中,@Options(useGeneratedKeys=true,keyColumn="id").
- SQL-记录查询篇-009
在学习记录查询之前,学习一些关键字的使用: 1.逻辑运算符:and . or . not .is null select * from table_name where id>2 and ...