Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 3
▶ 第二章,几个简单的程序
● 代码,单线程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h> #define SIZE (1024*1024)
#define MAXFLOP_ITER 100000000
#define LOOP_COUNT 128
#define FLOP_PER_CALC 2 float fa[SIZE] __attribute__((align()));
float fb[SIZE] __attribute__((align())); double dtime()
{
struct timeval mytime;
gettimeofday(&mytime, (struct timezone*));
return (double)(mytime.tv_sec + mytime.tv_usec*1.0e-6);
} int main(int argc, char *argv[])
{
const float a = 1.1; printf("Initializing\r\n");
for (int i = ; i < SIZE; i++)
{
fa[i] = (float)i + 0.1;
fb[i] = (float)i + 0.2;
} printf("Starting Compute\r\n");
double time_b, time_e;
time_b = dtime();
for (int j = ; j < MAXFLOP_ITER; j++)
{
for (int k = ; k < LOOP_COUNT; k++)
fa[k] = a * fa[k] + fb[k];
}
time_e = dtime(); double gflops = 1.0e-9 * LOOP_COUNT * MAXFLOP_ITER * FLOP_PER_CALC;
printf("GFlops = %10.3lf, Secs = %10.3lf, GFlops per sec = %10.3lf\r\n", gflops, time_e - time_b, gflops / (time_e - time_b)); return ;
}
■ 输出结果
GFlops = 25.600, Secs = 1.464, GFlops per sec = 17.484
● 单核心两线程的 OpenMP(注意总计算量提升了,而不是固定计算量看运行时间减少)
int main(int argc, char *argv[])
{
const float a = 1.1;
int i, j, k, numthreads; // 循环变量放到外边来 omp_set_num_threads(); // 运行时设置 OpenMP 参数
kmp_set_defaults("KMP_AFFINITY=compact"); #pragma omp parallel
#pragma omp master
numthreads = omp_get_num_threads(); printf("Initializing\r\n");
#pragma omp parallel for
for (i = ; i < SIZE; i++)
{
fa[i] = (float)i + 0.1;
fb[i] = (float)i + 0.2;
}
printf("Starting Compute on %d threads\r\n", numthreads);
double time_b, time_e;
time_b = dtime();
#pragma omp parallel for private(j, k)
for (i = ; i < numthreads; i++)
{
int offset = i * LOOP_COUNT;
for (j = ; j < MAXFLOP_ITER; j++)
{
for (k = ; k < LOOP_COUNT; k++)
fa[k + offset] = a * fa[k + offset] + fb[k + offset];
}
}
time_e = dtime(); double gflops = 1.0e-9 * numthreads * LOOP_COUNT * MAXFLOP_ITER * FLOP_PER_CALC;
printf("GFlops = %10.3lf, Secs = %10.3lf, GFlops per sec = %10.3lf\r\n", gflops, time_e - time_b, gflops / (time_e - time_b)); return ;
}
■ 输出结果
GFlops = 51.200, Secs = 1.464, GFlops per sec = 34.968
● 线程数、线程亲缘性调整
// 替换
omp_set_num_threads();
kmp_set_defaults("KMP_AFFINITY=compact");
// 替换为
omp_set_num_threads();
kmp_set_defaults("KMP_AFFINITY=scatter");
■ 输出结果
GFlops = 2867.200, Secs = 1.619, GFlops per sec = 1771.298
● 代码,带宽测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <omp.h> #define REAL double
#define SIZE (1000*1000*64)
#define MAXFLOP_ITER 1000
#define FLOP_PER_CALC 2 REAL fa[SIZE] __attribute__((align()));
REAL fb[SIZE] __attribute__((align()));
REAL fc[SIZE] __attribute__((align())); double dtime()
{
struct timeval mytime;
gettimeofday(&mytime, (struct timezone*));
return (double)(mytime.tv_sec + mytime.tv_usec*1.0e-6);
} int main(int argc, char *argv[])
{
const REAL a = 1.1;
int i, j; omp_set_num_threads();
kmp_set_defaults("KMP_AFFINITY=scatter"); printf("Initializing\r\n");
#pragma omp parallel for
for (i = ; i < SIZE; i++)
{
fa[i] = (REAL)i + 0.1;
fb[i] = (REAL)i + 0.2;
} #pragma omp parallel
#pragma omp master
printf("Starting BW Test on %d threads\r\n", omp_get_num_threads());
double time_b, time_e;
time_b = dtime();
for (i = ; i < MAXFLOP_ITER; i++)
{
#pragma omp parallel for
for (j = ; j < SIZE; j++)
fa[j] = fb[j];
}
time_e = dtime();
double gbytes = 1.0e-9 * MAXFLOP_ITER * SIZE * FLOP_PER_CALC * sizeof(REAL);
printf("Gbytes = %10.3lf, Secs = %10.3lf, GBytes per sec = %10.3lf\r\n", gbytes, time_e - time_b, gbytes / (time_e - time_b)); return ;
}
■ 输出结果
Starting BW Test on threads
Gbytes = 1024.000, Secs = 10.293, GBytes per sec = 99.488
● 代码,offload 模式(注意全局变量和编译选项的调整)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <omp.h> #define SIZE (1024*512)
#define MAXFLOP_ITER 100000000
#define LOOP_COUNT 128
#define FLOP_PER_CALC 2 __declspec (target(mic)) float fa[SIZE] __attribute__((align())); // 声明 mic 上的存储类型
__declspec (target(mic)) float fb[SIZE] __attribute__((align())); double dtime()
{
struct timeval mytime;
gettimeofday(&mytime, (struct timezone*));
return (double)(mytime.tv_sec + mytime.tv_usec*1.0e-6);
} int main(int argc, char *argv[])
{
const float a = 1.1;
int i, j, k, numthreads; omp_set_num_threads();
kmp_set_defaults("KMP_AFFINITY=scatter");
#pragma offload target (mic)// 声明需要使用 mic 的 offload 模式
#pragma omp parallel
#pragma omp master
numthreads = omp_get_num_threads(); printf("Initializing\r\n");
#pragma omp parallel for
for (i = ; i<SIZE; i++)
{
fa[i] = (float)i + 0.1;
fb[i] = (float)i + 0.2;
}
printf("Starting Compute on %d threads\r\n", numthreads);
double time_b, time_e;
time_b = dtime();
#pragma offload target (mic)// 声明需要使用 mic 的 offload 模式
#pragma omp parallel for private(j, k)
for (i = ; i<numthreads; i++)
{
int offset = i * LOOP_COUNT;
for (j = ; j < MAXFLOP_ITER; j++)
{
#pragma vector aligned// 强制向量对齐
for (k = ; k < LOOP_COUNT; k++)
fa[k + offset] = a * fa[k + offset] + fb[k + offset];
}
}
time_e = dtime(); double gflops = 1.0e-9 * numthreads * LOOP_COUNT * MAXFLOP_ITER * FLOP_PER_CALC;
printf("GFlops = %10.3lf, Secs = %10.3lf, GFlops per sec = %10.3lf\r\n", gflops, time_e - time_b, gflops / (time_e - time_b)); return ;
}
■ 输出结果
Starting Compute on threads
GFlops = 5734.400, Secs = 2.976, GFlops per sec = 1927.124
Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 3的更多相关文章
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 1
▶ 第三章,逐步优化了一个二维卷积计算的过程 ● 基准代码 #include <stdio.h> #include <stdlib.h> #include <string ...
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 4
▶ 第五章,几个优化 ● 代码 #include <stdio.h> #include <stdlib.h> #include <math.h> #define S ...
- 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,点 ...
随机推荐
- LeetCode 46 全排列
题目: 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3 ...
- javascript 跨域请求详细分析(终极跨域解决办法)
自从我接触前端以来,接手的项目里面很大部分都是前后端分离的,后端只提供接口,前端根据后端接口渲染出实际页面.个人觉得这是一个挺好的模式,前后端各自负责各自的模块,分工明确,而且也给前端更大的发挥空间. ...
- 还是畅通工程,最小生成树kruskal
题目描述: 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可 ...
- scrapy框架之递归解析和post请求
递归爬取解析多页页面数据 scrapy核心组件工作流程 scrapy的post请求发送 1.递归爬取解析多页页面数据 - 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储 - 需求分析 ...
- 利用Aspectj实现Oval的自动参数校验
前言: Oval参数校验框架确实小巧而强大, 他通过注解的方式配置类属性, 然后通过Oval本身自带的工具类, 快速便捷执行参数校验. 但是工具类的校验需要额外的代码编写, 同时Oval对函数参数级的 ...
- JAVA高级篇(二、JVM内存模型、内存管理之第二篇)
本文转自https://zhuanlan.zhihu.com/p/25713880. JVM的基础概念 JVM的中文名称叫Java虚拟机,它是由软件技术模拟出计算机运行的一个虚拟的计算机. JVM也充 ...
- [LeetCode&Python] Problem 674. Longest Continuous Increasing Subsequence
Given an unsorted array of integers, find the length of longest continuousincreasing subsequence (su ...
- es6学习日记5-对象的扩展
属性的简洁表示法 ES6 允许直接写入变量和函数,作为对象的属性和方法.这样的书写更加简洁. const foo = 'bar'; const baz = {foo}; baz // {foo: &q ...
- js空数组
首先我们定义一个空的数组: var a = [ ]; 数组a里面是空的没有值,接下来我们打印: console.log(!!a); 因为数组是空的,此处应该为false. 恰好相反,!!a为true. ...
- 基于 Jenkins 构建持续集成任务
1.1 Jenkins 配置使用心得 我是在windows10上安装的,安装过程很简单,从官网上下载下来msi安装包,双击执行就好了.安装程序完成后会自动打开http://localhost:8080 ...