由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 问一个并行计算的问题
进入Programming版参与讨论
1 (共1页)
l*******s
发帖数: 7316
1
没找到更合适的版面讨论这个问题,就在这里问吧.
我发现OpenMP的reduction效率很差,做同样的两个向量的内积,MPI要比OpenMP还快。
MPI是分布内存,需要信息交换才能完成reduction。 结果比使用共享内存的OpenMP还
快。
这说明OpenMP的reduction没有搞好。我不知道是我使用的系统的问题还是普遍问题。
有人有类似的经验吗? 怎么解决?
我提供了一个code,然后再大家的反馈后做了修改。 现在把code也帖再这里。
省得大家爬楼。
现在的code 还是模仿dot product, 只不过 element都是compute on the fly.
所以code中没有大的数组,减少cache missing。
我还特意使用了一个sin function,
这样是的新的dot product 跟前面的 dot product的关系更复杂,
以免在element计算中的sum被优化掉。
这样做是为了让大家的注意力集中在reduction上。
请各位帮忙测试一下performance, 或者找到优化方法。多谢。
我的测试结果
OMP
sum = 6992.953984, time = 0.409850 sec, np = 1
sum = 6992.953984, time = 0.270875 sec, np = 2
sum = 6992.953984, time = 0.186024 sec, np = 4
sum = 6992.953984, time = 0.144010 sec, np = 8
sum = 6992.953984, time = 0.115188 sec, np = 16
sum = 6992.953984, time = 0.195485 sec, np = 32
MPI
sum = 6992.953984, time = 0.381701 sec, np = 1
sum = 6992.953984, time = 0.243513 sec, np = 2
sum = 6992.953984, time = 0.158326 sec, np = 4
sum = 6992.953984, time = 0.102489 sec, np = 8
sum = 6992.953984, time = 0.063975 sec, np = 16
sum = 6992.953984, time = 0.044748 sec, np = 32
很明显,MPI的reduction比OMP效率高,但我认为OMP应该能做到比MPI好。
这是MPI的code,
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int np, my_rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &np);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int n = 10000;
int repeat = 10000;
int sublength = (int)(ceil((double)(n) / (double)(np)));
int nstart = my_rank * sublength;
int nend = nstart + sublength;
if (nend >n )
{
nend = n;
sublength = nend - nstart;
}
double dot = 0;
double loc_dot = 0;
double sum = 1;
int j, k;
double t, time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
MPI_Allreduce(&loc_dot, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
sum += (dot/(double)(n));
loc_dot = 0;
}
time += omp_get_wtime();
MPI_Allreduce(&time, &t, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
if (my_rank == 0)
printf("sum = %f, time = %f sec, np = %d\n", sum, t, np);
return 0;
}
这是OMP的code
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 10000;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
double loc_dot = 0;
double sum = 1;
#pragma omp parallel
{
int i, j, k;

double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
#pragma omp for reduction(+: loc_dot)
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
#pragma omp single
{
sum += (loc_dot/(double)(n));
loc_dot =0;
}
}
time += omp_get_wtime();
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %d\n", sum, time, np);
}

return 0;
}
m*****p
发帖数: 39
2
你用的什麼CPU?openmp只適合單機多cpu多核架構,不適合多機器架構。一般我們mpi
和openmp同時用,mpi用來跨機器,openmp是單機內部
l*******s
发帖数: 7316
3
我是多機器架構,mpi和omp同时使用。但基本上只用mpi的效果往往超过同时使用。
所以我把问题简化成单机多cpu的情况, 可以直接对比mpi和omp。
也就是说,我只用多机中的一个share memory的node来测试。

mpi

【在 m*****p 的大作中提到】
: 你用的什麼CPU?openmp只適合單機多cpu多核架構,不適合多機器架構。一般我們mpi
: 和openmp同時用,mpi用來跨機器,openmp是單機內部

m*****p
发帖数: 39
4
單機可以用Linux perf一下看看哪裡是瓶頸,event可以是cycle或者cache miss。如果
是intel,可以vtune,如果是amd,可以uprof。Linux perf也可以看branch miss rate
,先搞清楚是frontend還是backend pressure。

【在 l*******s 的大作中提到】
: 我是多機器架構,mpi和omp同时使用。但基本上只用mpi的效果往往超过同时使用。
: 所以我把问题简化成单机多cpu的情况, 可以直接对比mpi和omp。
: 也就是说,我只用多机中的一个share memory的node来测试。
:
: mpi

l*******s
发帖数: 7316
5
机器是Intel(R) Xeon(R) Gold 6152 CPU @ 2.10GHz
OS是 CentOS-7.
没用过perf, 怎么用?

rate

【在 m*****p 的大作中提到】
: 單機可以用Linux perf一下看看哪裡是瓶頸,event可以是cycle或者cache miss。如果
: 是intel,可以vtune,如果是amd,可以uprof。Linux perf也可以看branch miss rate
: ,先搞清楚是frontend還是backend pressure。

m*****p
发帖数: 39
6
https://www.brendangregg.com/perf.html 如果了解CPU架構和PMU的需要一個月上手。
不了解CPU內部的,回去複習一下計算機微架構:https://en.wikichip.org/wiki/
intel/microarchitectures/skylake_(server)
估計一年後可以搞定。
l*******s
发帖数: 7316
7
可以请帮忙在你的机器上测试一下MPI 和OMP的reduction的效率?
我给你提供code, 帮我测试一下1,2,4,8,16 个processors的运行时间。
看看是不是跟我得到的近似。多谢。
下面的code 在看到大家的回复后做了一些修改。
所以中间帖子里的timing可能不一致。但规律都是一样的
这是MPI的code,
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int np, my_rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &np);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int n = 10000;
int repeat = 10000;
int sublength = (int)(ceil((double)(n) / (double)(np)));
int nstart = my_rank * sublength;
int nend = nstart + sublength;
if (nend >n )
{
nend = n;
sublength = nend - nstart;
}
double dot = 0;
double loc_dot = 0;
double sum = 1;
int j, k;
double t, time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
MPI_Allreduce(&loc_dot, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
sum += (dot/(double)(n));
loc_dot = 0;
}
time += omp_get_wtime();
MPI_Allreduce(&time, &t, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
if (my_rank == 0)
printf("sum = %f, time = %f sec, np = %d\n", sum, t, np);
return 0;
}
这是OMP的code
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 10000;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
double loc_dot = 0;
double sum = 1;
#pragma omp parallel
{
int i, j, k;

double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
#pragma omp for reduction(+: loc_dot)
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
#pragma omp single
{
sum += (loc_dot/(double)(n));
loc_dot =0;
}
}
time += omp_get_wtime();
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %d\n", sum, time, np);
}

return 0;
}
m*****p
发帖数: 39
8
你建立一個github吧,把makefile也放上,我有時間試試
l*******s
发帖数: 7316
9
不用makefile
这code只有一个文件。
假如mpi code文件名是 reduct_mpi.c
编译命令 mpiicc -qopenmp reduct_mpi.c -o reduct_mpi
执行方式 mpiexec -n 4 ./reduct_mpi
其中4是 number of processor, 可以改成 1、2、8、16等
假如omp code文件名是 reduct_omp.c
编译命令 mpiicc -qopenmp reduct_omp.c -o reduct_omp
执行方式 ./reduct_omp 4
其中4是 number of processor, 可以改成 1、2、8、16等

【在 m*****p 的大作中提到】
: 你建立一個github吧,把makefile也放上,我有時間試試
n******t
发帖数: 4406
10
你這個算dot product的,第一件事應該是去用blas的ddot,然後才去想並行的事。

【在 l*******s 的大作中提到】
: 可以请帮忙在你的机器上测试一下MPI 和OMP的reduction的效率?
: 我给你提供code, 帮我测试一下1,2,4,8,16 个processors的运行时间。
: 看看是不是跟我得到的近似。多谢。
: 下面的code 在看到大家的回复后做了一些修改。
: 所以中间帖子里的timing可能不一致。但规律都是一样的
: 这是MPI的code,
: #include
: #include
: #include
: #include

l*******s
发帖数: 7316
11
这不是我实用的code,只是用了测试reduction的。

【在 n******t 的大作中提到】
: 你這個算dot product的,第一件事應該是去用blas的ddot,然後才去想並行的事。
n******t
发帖数: 4406
12
不是你要跑的code,調性能其實就沒什麼用,因爲並行和任務關係太大。
比如說你這個程序,你試着把n加兩個0,把repeat減兩個0你就知道我的意思了。

【在 l*******s 的大作中提到】
: 这不是我实用的code,只是用了测试reduction的。
l*******s
发帖数: 7316
13
我知道。 所以我选的n有代表性, repeat选足够大来使得测试时间比较稳定。

【在 n******t 的大作中提到】
: 不是你要跑的code,調性能其實就沒什麼用,因爲並行和任務關係太大。
: 比如說你這個程序,你試着把n加兩個0,把repeat減兩個0你就知道我的意思了。

n******t
发帖数: 4406
14
你有意選N讓CPU一件事情沒幹多久就停掉然後不停地create 線程?你最後基本上在測
create線程的速度,沒point吧。

【在 l*******s 的大作中提到】
: 我知道。 所以我选的n有代表性, repeat选足够大来使得测试时间比较稳定。
l*******s
发帖数: 7316
15
这是我的最简单版本。我有一个改进版本,可以不用不停地create 線程,
看下面的code。因为稍复杂一些,所以没有在前帖中给出。
我需要的就是有很多dotproduct,但不是简单的loop。
想要对每个dotproduct 并行。结果OMP的效果没有MPI好。
这个改进版,比前面最简单的版本好一点,但还是不如MPI。
所以除了create线程的问题外,最主要的问题还是reduction。
如果去掉reduction,基本上运行时间可以达到 1/np
#include
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 100000;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
double* a = malloc(sublength * sizeof(double));
double* b = malloc(sublength * sizeof(double));
double loc_dot = 0;
double sum = 0;
#pragma omp parallel
{
int i, j, k;
#pragma omp for
for (k = 0; k < sublength; k++)
{
i = k + nstart;
double temp = sin(i / 3.1415926 + 0.01);
a[k] = temp;
b[k] = temp;
}
double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
#pragma omp for reduction(+: loc_dot)
for (k = 0; k < sublength; k++)
{
loc_dot += a[k] * b[k];
}
#pragma omp single nowait
{
sum += loc_dot;
loc_dot =0;
}
}
time += omp_get_wtime();
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %dn", sum, time, np);
}

return 0;
}

【在 n******t 的大作中提到】
: 你有意選N讓CPU一件事情沒幹多久就停掉然後不停地create 線程?你最後基本上在測
: create線程的速度,沒point吧。

m*****p
发帖数: 39
16
Linking error,你看看你用了什麼lib,需不需要lm
l*******s
发帖数: 7316
17
我没有用特殊的lib,只load了一个module:intel/18.0.1
其他的head file 也可以不需要。只要下面这两个。
#include
#include

【在 m*****p 的大作中提到】
: Linking error,你看看你用了什麼lib,需不需要lm
m*****p
发帖数: 39
18
你的測試輸出時間不對,單機64核實際運行時間:
mpi是4.28秒,omp是1.44秒。
但是你輸出的mpi結果是0.61秒,omp是1.436秒。
perf顯示mpi佔用更多資源,只有2% frontend idle,相比之下omp有50%frontend idle
,只有七分之一的branches,十分之一的context-switches。這個測試是frontend
bounded。
l*******s
发帖数: 7316
19
我编译的时候需要这个option, -qopenmp
你可能要改成你编译openmp code需要的option 可能是 -fopenmp
还有 omp.h 所在的路径。其他就没什么需要注意的了

【在 m*****p 的大作中提到】
: Linking error,你看看你用了什麼lib,需不需要lm
n******t
发帖数: 4406
20
你具體貼一下你的時間唄。
但是你並沒有搞懂我的意思,你這個東西的關鍵點在於任務切太碎了,好比每個cpu沒
有餵飽就把碗拿走了。這個你不管用MPI還是OPENMP都沒用的。

【在 l*******s 的大作中提到】
: 这是我的最简单版本。我有一个改进版本,可以不用不停地create 線程,
: 看下面的code。因为稍复杂一些,所以没有在前帖中给出。
: 我需要的就是有很多dotproduct,但不是简单的loop。
: 想要对每个dotproduct 并行。结果OMP的效果没有MPI好。
: 这个改进版,比前面最简单的版本好一点,但还是不如MPI。
: 所以除了create线程的问题外,最主要的问题还是reduction。
: 如果去掉reduction,基本上运行时间可以达到 1/np
: #include
: int main(int argc, char* argv[])
: {

l*******s
发帖数: 7316
21
输出的是100Kdot product的时间
1 processor, mpi=0.396, omp1=0.537,omp2=0.523;
2 processors,mpi=0.309, omp1=0.430,omp2=0.399;
4 processors,mpi=0.231, omp1=0.375,omp2=0.339;
8 processors,mpi=0.167, omp1=0.378,omp2=0.305;
16 processors,mpi=0.163, omp1=0.595,omp2=0.357
你是说omp_get_wtime()测试不准吗?
omp_get_wtime()的resolution是 1E-7 秒。

idle

【在 m*****p 的大作中提到】
: 你的測試輸出時間不對,單機64核實際運行時間:
: mpi是4.28秒,omp是1.44秒。
: 但是你輸出的mpi結果是0.61秒,omp是1.436秒。
: perf顯示mpi佔用更多資源,只有2% frontend idle,相比之下omp有50%frontend idle
: ,只有七分之一的branches,十分之一的context-switches。這個測試是frontend
: bounded。

l*******s
发帖数: 7316
22
我知道这个问题,但我想要OMP至少可以达到MPI的速度。
这样我可以找到最优的thread number。
比如说同样是做10000个element的向量的dotproduct, MPI可以用到16个process,
但OMP最多只能用8个。再多速度就下降了。
我的code里有很多dot product,dot product可以并行,但dot product之间不能并行。
OMP在其他方面比MPI好,但reduction比较差,我只想知道是不是只有我遇到这个问题。

【在 n******t 的大作中提到】
: 你具體貼一下你的時間唄。
: 但是你並沒有搞懂我的意思,你這個東西的關鍵點在於任務切太碎了,好比每個cpu沒
: 有餵飽就把碗拿走了。這個你不管用MPI還是OPENMP都沒用的。

l*******s
发帖数: 7316
23
我也用 perf stat 输出运行时间。
程序执行总时间比我在程序里输出的时间稍多一点,看起来测试时间是对的。
比如
perf stat mpiexec -n 16 reduction_mpi
sum = 499907924.429987, time = 0.160385 sec, np = 16
Performance counter stats for 'mpiexec -n 16 reduction_mpi':
2,970.27 msec task-clock:u # 12.556 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
38,117 page-faults:u # 0.013 M/sec
5,232,710,936 cycles:u # 1.762 GHz
3,932,532,053 instructions:u # 0.75 insn per cycle
549,130,804 branches:u # 184.876 M/sec
2,682,456 branch-misses:u # 0.49% of all branches
0.236558883 seconds time elapsed
2.684250000 seconds user
0.297384000 seconds sys
这是16核MPI, 总时间是0.236558883 seconds, 我的code输出100K内积时间是0.
160385 sec
perf stat reduction_omp 16
sum = 499907924.429987, time = 0.446216 sec, np = 16
Performance counter stats for 'reduction_omp 16':
7,133.38 msec task-clock:u # 15.584 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
820 page-faults:u # 0.115 K/sec
19,093,137,129 cycles:u # 2.677 GHz
6,447,752,697 instructions:u # 0.34 insn per cycle
1,264,314,844 branches:u # 177.239 M/sec
3,294,979 branch-misses:u # 0.26% of all branches
0.457738534 seconds time elapsed
7.131633000 seconds user
0.005982000 seconds sys
这是16核OMP, 总时间是0.457738534 seconds, 我的code输出100K内积时间是0.
446216 sec
不知道你说的实际时间是怎么测得的.

【在 l*******s 的大作中提到】
: 输出的是100Kdot product的时间
: 1 processor, mpi=0.396, omp1=0.537,omp2=0.523;
: 2 processors,mpi=0.309, omp1=0.430,omp2=0.399;
: 4 processors,mpi=0.231, omp1=0.375,omp2=0.339;
: 8 processors,mpi=0.167, omp1=0.378,omp2=0.305;
: 16 processors,mpi=0.163, omp1=0.595,omp2=0.357
: 你是说omp_get_wtime()测试不准吗?
: omp_get_wtime()的resolution是 1E-7 秒。
:
: idle

l*******s
发帖数: 7316
24
请在64核的机子上测一下只用32核或更少核的时间。
用满64核可能performence会很差。
另外,你测的OMP是我15楼的改进版本吗?

idle

【在 m*****p 的大作中提到】
: 你的測試輸出時間不對,單機64核實際運行時間:
: mpi是4.28秒,omp是1.44秒。
: 但是你輸出的mpi結果是0.61秒,omp是1.436秒。
: perf顯示mpi佔用更多資源,只有2% frontend idle,相比之下omp有50%frontend idle
: ,只有七分之一的branches,十分之一的context-switches。這個測試是frontend
: bounded。

g****t
发帖数: 31659
25
你這個程序。跑一百次得到的時間之波動大嗎?
若我計時。會紀錄一個開始時間,一個結束時間。
中間loop一萬次。然後 時間/10k。
此法比簡單強壯。不涉及計算時間之overhead等細節。


: 我也用 perf stat 输出运行时间。

: 程序执行总时间比我在程序里输出的时间稍多一点,看起来测试时间是对
的。

: 比如

: perf stat mpiexec -n 16 reduction_mpi

: sum = 499907924.429987, time = 0.160385 sec, np = 16

: Performance counter stats for 'mpiexec -n 16 reduction_mpi':

: 2,970.27 msec task-clock:u # 12.556
CPUs
utilized

: 0 context-switches:u # 0.000 K/
sec

: 0 cpu-migrations:u # 0.000 K/
sec

: 38,117 page-faults:u # 0.013 M/
sec



【在 l*******s 的大作中提到】
: 请在64核的机子上测一下只用32核或更少核的时间。
: 用满64核可能performence会很差。
: 另外,你测的OMP是我15楼的改进版本吗?
:
: idle

n******t
发帖数: 4406
26
你這個的n和repeat是你程序里的?
應該不是gcc的編譯吧。

【在 l*******s 的大作中提到】
: 输出的是100Kdot product的时间
: 1 processor, mpi=0.396, omp1=0.537,omp2=0.523;
: 2 processors,mpi=0.309, omp1=0.430,omp2=0.399;
: 4 processors,mpi=0.231, omp1=0.375,omp2=0.339;
: 8 processors,mpi=0.167, omp1=0.378,omp2=0.305;
: 16 processors,mpi=0.163, omp1=0.595,omp2=0.357
: 你是说omp_get_wtime()测试不准吗?
: omp_get_wtime()的resolution是 1E-7 秒。
:
: idle

l*******s
发帖数: 7316
27
波动比较大,std/avg 大约能到10%。
我已经loop了100K次了,可以改成1M次,运行时间也就是几秒钟。
立等可取

【在 g****t 的大作中提到】
: 你這個程序。跑一百次得到的時間之波動大嗎?
: 若我計時。會紀錄一個開始時間,一個結束時間。
: 中間loop一萬次。然後 時間/10k。
: 此法比簡單強壯。不涉及計算時間之overhead等細節。
:
:
: 我也用 perf stat 输出运行时间。
:
: 程序执行总时间比我在程序里输出的时间稍多一点,看起来测试时间是对
: 的。
:
: 比如
:
: perf stat mpiexec -n 16 reduction_mpi

l*******s
发帖数: 7316
28
n是我要用的size, repeat只是用来得到可靠的测试时间。
在我实用的程序里也会出现100K次,只是每次数据都不一样。

【在 n******t 的大作中提到】
: 你這個的n和repeat是你程序里的?
: 應該不是gcc的編譯吧。

n******t
发帖数: 4406
29
大部分人沒有理解並行計算需要的不是找到最優的thread number,而是需要找到最優
的工作量。像你這種cpu bound的計算,工作量找對了應該一直是linear scale的。
你把10000改成1000000,你就知道我說的是啥了。

行。
题。

【在 l*******s 的大作中提到】
: 我知道这个问题,但我想要OMP至少可以达到MPI的速度。
: 这样我可以找到最优的thread number。
: 比如说同样是做10000个element的向量的dotproduct, MPI可以用到16个process,
: 但OMP最多只能用8个。再多速度就下降了。
: 我的code里有很多dot product,dot product可以并行,但dot product之间不能并行。
: OMP在其他方面比MPI好,但reduction比较差,我只想知道是不是只有我遇到这个问题。

g****t
发帖数: 31659
30
不用perf,就naive start time , end time呢?
可能你得先把波動原因找到。這可能是計算時間的問題。
若單次時間波動大。則結論是否沒啥意義。


: 波动比较大,std/avg 大约能到10%。

: 我已经loop了100K次了,可以改成1M次,运行时间也就是几秒钟。

: 立等可取



【在 l*******s 的大作中提到】
: n是我要用的size, repeat只是用来得到可靠的测试时间。
: 在我实用的程序里也会出现100K次,只是每次数据都不一样。

l*******s
发帖数: 7316
31
并行计算找最优工作量才是搞计算的人骗钱的伎俩。
为了并行效率而增加工作量毫无意义。
现在问题是工作量是固定的,假设你有足够的计算资源,怎么能算的最快。
或者在现有的计算资源条件下,怎么算的最快。
而不是任意增加工作量。

【在 n******t 的大作中提到】
: 大部分人沒有理解並行計算需要的不是找到最優的thread number,而是需要找到最優
: 的工作量。像你這種cpu bound的計算,工作量找對了應該一直是linear scale的。
: 你把10000改成1000000,你就知道我說的是啥了。
:
: 行。
: 题。

g****t
发帖数: 31659
32
38,117 page-faults:u # 0.013 M/sec
page faults應是各項裡最cost的。改下數組size應能提速。


: 我也用 perf stat 输出运行时间。

: 程序执行总时间比我在程序里输出的时间稍多一点,看起来测试时间是对的。

: 比如

: perf stat mpiexec -n 16 reduction_mpi

: sum = 499907924.429987, time = 0.160385 sec, np = 16

: Performance counter stats for 'mpiexec -n 16 reduction_mpi':

: 2,970.27 msec task-clock:u # 12.556 CPUs
utilized

: 0 context-switches:u # 0.000 K/sec

: 0 cpu-migrations:u # 0.000 K/sec

: 38,117 page-faults:u # 0.013 M/sec



【在 l*******s 的大作中提到】
: 并行计算找最优工作量才是搞计算的人骗钱的伎俩。
: 为了并行效率而增加工作量毫无意义。
: 现在问题是工作量是固定的,假设你有足够的计算资源,怎么能算的最快。
: 或者在现有的计算资源条件下,怎么算的最快。
: 而不是任意增加工作量。

l*******s
发帖数: 7316
33
并行计算中的波动时不可避免的。
我觉得10%还好。我现在时100K次平均值还有10%的波动,
单次的波动可能更大。
但总体规律还是有用的。

【在 g****t 的大作中提到】
: 不用perf,就naive start time , end time呢?
: 可能你得先把波動原因找到。這可能是計算時間的問題。
: 若單次時間波動大。則結論是否沒啥意義。
:
:
: 波动比较大,std/avg 大约能到10%。
:
: 我已经loop了100K次了,可以改成1M次,运行时间也就是几秒钟。
:
: 立等可取
:

g****t
发帖数: 31659
34
給定硬件,如何計算最快?
這問題實際上是不確定的。沒有固定答案。原因是
現有之OS里有大批的啟發式算法。開機硬件就根據硬件情況建立各種表格/數據結構。
例如計算物理內存地址之用的表格。然後後續軟件還會更新這些東西的。
極大數組,極小數組。相對來說結果一致性會好些。


: 并行计算找最优工作量才是搞计算的人骗钱的伎俩。

: 为了并行效率而增加工作量毫无意义。

: 现在问题是工作量是固定的,假设你有足够的计算资源,怎么能算的最快。

: 或者在现有的计算资源条件下,怎么算的最快。

: 而不是任意增加工作量。



【在 l*******s 的大作中提到】
: 并行计算中的波动时不可避免的。
: 我觉得10%还好。我现在时100K次平均值还有10%的波动,
: 单次的波动可能更大。
: 但总体规律还是有用的。

g****t
发帖数: 31659
35
Conclusion的一致性如何?是否永遠一法好過另一法?


: 并行计算中的波动时不可避免的。

: 我觉得10%还好。我现在时100K次平均值还有10%的波动,

: 单次的波动可能更大。

: 但总体规律还是有用的。



【在 l*******s 的大作中提到】
: 并行计算中的波动时不可避免的。
: 我觉得10%还好。我现在时100K次平均值还有10%的波动,
: 单次的波动可能更大。
: 但总体规律还是有用的。

l*******s
发帖数: 7316
36
数组的size变化没有意义。
但是可以改变omp for schedule, 也就是各个thread处理的k值范围。
也就是把数组分成块。
但目前用缺省的好像最优。
实际上, 通过我的测试page missing并不是最大问题,问题在于reduction,
如果我去掉reduction, 马上变成linear scalable。

【在 g****t 的大作中提到】
: 38,117 page-faults:u # 0.013 M/sec
: page faults應是各項裡最cost的。改下數組size應能提速。
:
:
: 我也用 perf stat 输出运行时间。
:
: 程序执行总时间比我在程序里输出的时间稍多一点,看起来测试时间是对的。
:
: 比如
:
: perf stat mpiexec -n 16 reduction_mpi
:
: sum = 499907924.429987, time = 0.160385 sec, np = 16
:
: Performance counter stats for 'mpiexec -n 16 reduction_mpi':
:
: 2,970.27 msec task-clock:u # 12.556 CPUs

g****t
发帖数: 31659
37
數組尺寸會影響memory page 算法。影響到access 數組元素之速度。
小程序應能測出是否問題在於access time。


: 数组的size变化没有意义。

: 但是可以改变omp for schedule, 也就是各个thread处理的k值范围。

: 也就是把数组分成块。

: 但目前用缺省的好像最优。



【在 l*******s 的大作中提到】
: 数组的size变化没有意义。
: 但是可以改变omp for schedule, 也就是各个thread处理的k值范围。
: 也就是把数组分成块。
: 但目前用缺省的好像最优。
: 实际上, 通过我的测试page missing并不是最大问题,问题在于reduction,
: 如果我去掉reduction, 马上变成linear scalable。

l*******s
发帖数: 7316
38
是的。但你刚才看见的有很多page fault 是MPI,OMP 的page fault 很少,但还是比
MPI慢,原因就是reduction没做好。

【在 g****t 的大作中提到】
: 數組尺寸會影響memory page 算法。影響到access 數組元素之速度。
: 小程序應能測出是否問題在於access time。
:
:
: 数组的size变化没有意义。
:
: 但是可以改变omp for schedule, 也就是各个thread处理的k值范围。
:
: 也就是把数组分成块。
:
: 但目前用缺省的好像最优。
:

m*****p
发帖数: 39
39
64核 2.2-2.7GHz 單路CPU,openmpi 4.0.6 with ucx,Ubuntu 20.04.2
mpi時間沒有加入系統啟動時間,sys wall clock實際顯示mpi更慢。
mpi perf time / mpi time:
1 4.87秒 / 2.67秒
2 3.57秒 / 1.36秒
4 2.00秒 / 0.79秒
8 0.85秒 / 0.57秒
16 0.97秒 / 0.47秒
24 3.13秒 / 0.47秒
32 3.30秒 / 0.46秒
48 3.77秒 / 0.52秒
64 4.21秒 / 0.61秒
omp perf time:
1 2.68秒
2 1.46秒
4 0.93秒
8 0.72秒
16 0.93秒
24 1.00秒
32 0.98秒
48 1.18秒
64 1.40秒
omp2 perf time:
1 2.68秒
2 1.39秒
4 0.77秒
8 0.53秒
16 0.52秒
24 0.48秒
32 0.49秒
48 0.50秒
64 0.57秒
j**f
发帖数: 28
40
用全部核performence变差很可能是schedule有问题, 不同的schedule对速度影响很大
intel的编译器曾经需要强制
export KMP_AFFINITY=compact
如果用满64核时,仍有cpu是idle的,就说明这个问题还存在。
openmp 默认的schedule 会disalbe SIMD, 而你的代码明显可以SIMD加速

【在 l*******s 的大作中提到】
: 请在64核的机子上测一下只用32核或更少核的时间。
: 用满64核可能performence会很差。
: 另外,你测的OMP是我15楼的改进版本吗?
:
: idle

j**f
发帖数: 28
41
n太小,也就够喂报2个线程,线程多了以后就是线程之间在抢资源。

【在 m*****p 的大作中提到】
: 64核 2.2-2.7GHz 單路CPU,openmpi 4.0.6 with ucx,Ubuntu 20.04.2
: mpi時間沒有加入系統啟動時間,sys wall clock實際顯示mpi更慢。
: mpi perf time / mpi time:
: 1 4.87秒 / 2.67秒
: 2 3.57秒 / 1.36秒
: 4 2.00秒 / 0.79秒
: 8 0.85秒 / 0.57秒
: 16 0.97秒 / 0.47秒
: 24 3.13秒 / 0.47秒
: 32 3.30秒 / 0.46秒

l*******s
发帖数: 7316
42
我测的时间不太一样
mpi perf time / dotp time /perf-dotp time:
1 0.485秒 / 0.418秒 /0.067
2 0.325秒 / 0.267秒 /0.058
4 0.282秒 / 0.233秒 /0.049
8 0.225秒 / 0.165秒 /0.060
16 0.253秒 / 0.170秒 /0.083
32 0.284秒 / 0.188秒 /0.096
OMP2 perf time / dotp time:
1 0.473秒 / 0.460秒 /0.013
2 0.386秒 / 0.373秒 /0.013
4 0.338秒 / 0.325秒 /0.013
8 0.372秒 / 0.358秒 /0.014
16 0.538秒 / 0.512秒 /0.016
32 0.683秒 / 0.662秒 /0.021
MPI的dotproduct之外的时间确实比OMP多,但不影响结论。
MPI是8核时间最短,OMP是4核。
其实上dotproduct之外的时间对我的研究没影响。
因为其他还有很多并行效率较高的工作量。我都省略了。
只研究dot product,特别是reduction的效率。
你的运行时间有两点比较奇怪。
第一: 时间基本上是我的运行时间的5倍, 但机器的配置差不多。
第二: MPI的启动时间在8核以下基本跟dotproduct时间相当。而我的只有1/6,左右。
我怀疑跟编译系统有关。 我用的是 intel 编译系统 18.0.1.
你测的时间一个好的地方是OMP一直到24核时间还在减少,而我机器上8核就回头了。
下面是机器的配置
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 44
On-line CPU(s) list: 0-43
Thread(s) per core: 1
Core(s) per socket: 22
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6152 CPU @ 2.10GHz
Stepping: 4
CPU MHz: 1000.012
CPU max MHz: 3700.0000
CPU min MHz: 1000.0000
BogoMIPS: 4200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 30976K

【在 m*****p 的大作中提到】
: 64核 2.2-2.7GHz 單路CPU,openmpi 4.0.6 with ucx,Ubuntu 20.04.2
: mpi時間沒有加入系統啟動時間,sys wall clock實際顯示mpi更慢。
: mpi perf time / mpi time:
: 1 4.87秒 / 2.67秒
: 2 3.57秒 / 1.36秒
: 4 2.00秒 / 0.79秒
: 8 0.85秒 / 0.57秒
: 16 0.97秒 / 0.47秒
: 24 3.13秒 / 0.47秒
: 32 3.30秒 / 0.46秒

l*******s
发帖数: 7316
43
你用的是gcc + openmpi吗?

【在 m*****p 的大作中提到】
: 64核 2.2-2.7GHz 單路CPU,openmpi 4.0.6 with ucx,Ubuntu 20.04.2
: mpi時間沒有加入系統啟動時間,sys wall clock實際顯示mpi更慢。
: mpi perf time / mpi time:
: 1 4.87秒 / 2.67秒
: 2 3.57秒 / 1.36秒
: 4 2.00秒 / 0.79秒
: 8 0.85秒 / 0.57秒
: 16 0.97秒 / 0.47秒
: 24 3.13秒 / 0.47秒
: 32 3.30秒 / 0.46秒

n******t
发帖数: 4406
44
你完全沒搞明白我的意思。
工作總量不變,每個分片多大是關鍵,懂了?
還是那句話,你把你的每個分片加大,repeat減少,你的工作總量不會變,就知道我的
意思了。

【在 l*******s 的大作中提到】
: 并行计算找最优工作量才是搞计算的人骗钱的伎俩。
: 为了并行效率而增加工作量毫无意义。
: 现在问题是工作量是固定的,假设你有足够的计算资源,怎么能算的最快。
: 或者在现有的计算资源条件下,怎么算的最快。
: 而不是任意增加工作量。

n******t
发帖数: 4406
45
你要真care這個,就應該先回到如何一個CPU跑得更快的事情上面來。
sum = 499999156.515837, time = 0.028685 sec, np = 1n
這個是我用一個core,一模一樣的cpu跑你的程序的結果。

【在 l*******s 的大作中提到】
: 并行计算找最优工作量才是搞计算的人骗钱的伎俩。
: 为了并行效率而增加工作量毫无意义。
: 现在问题是工作量是固定的,假设你有足够的计算资源,怎么能算的最快。
: 或者在现有的计算资源条件下,怎么算的最快。
: 而不是任意增加工作量。

l*******s
发帖数: 7316
46
都说了,能并行的就是一个个的dot product. 怎么增大。能增大早就做了。

【在 n******t 的大作中提到】
: 你完全沒搞明白我的意思。
: 工作總量不變,每個分片多大是關鍵,懂了?
: 還是那句話,你把你的每個分片加大,repeat減少,你的工作總量不會變,就知道我的
: 意思了。

n******t
发帖数: 4406
47
OK,首先知道能增大是關鍵,我們再說怎麼增大。
第一,我還是建議你先優化單CPU,沒有這個別的都是扯蛋的。
第二,你這個情況需要另外寫一個pipeline來sched你的work,把你的dot product的任
務都合併掉。
實際上爲什麼MPI再你的情況下會快,我most likely覺得是因爲MPI implicitly做了合
併工作,屬於用延遲換帶寬的做法。但是畢竟是亂撞的結果,所以和有意識的調整還是
有很大差距的。

【在 l*******s 的大作中提到】
: 都说了,能并行的就是一个个的dot product. 怎么增大。能增大早就做了。
l*******s
发帖数: 7316
48
我用gcc 得到了跟你的类似的结果, 但比intel 慢。
gcc compiler
OMP2 perf time / dotp time:
1 2.65秒 / 2.64秒
2 1.60秒 / 1.59秒
4 0.877秒 / 0.870秒
8 0.688秒 / 0.680秒
16 0.594秒 / 0.587秒
32 0.846秒 / 0.837秒
intel compiler
OMP2 perf time / dotp time:
1 0.473秒 / 0.460秒 /0.013
2 0.386秒 / 0.373秒 /0.013
4 0.338秒 / 0.325秒 /0.013
8 0.372秒 / 0.358秒 /0.014
16 0.538秒 / 0.512秒 /0.016
32 0.683秒 / 0.662秒 /0.021

【在 m*****p 的大作中提到】
: 64核 2.2-2.7GHz 單路CPU,openmpi 4.0.6 with ucx,Ubuntu 20.04.2
: mpi時間沒有加入系統啟動時間,sys wall clock實際顯示mpi更慢。
: mpi perf time / mpi time:
: 1 4.87秒 / 2.67秒
: 2 3.57秒 / 1.36秒
: 4 2.00秒 / 0.79秒
: 8 0.85秒 / 0.57秒
: 16 0.97秒 / 0.47秒
: 24 3.13秒 / 0.47秒
: 32 3.30秒 / 0.46秒

n******t
发帖数: 4406
49
你如果搞懂我的意思,你看到的應該是這個。還是和你一模一樣的CPU。這個並沒有對
單CPU做優化,只是修改掉調度單位而已。
./b sum = 499999156.515833, time = 1.436360 sec, np = 1n
./b 2 sum = 499999156.515837, time = 0.719677 sec, np = 2n
./b 4 sum = 499999156.515837, time = 0.360384 sec, np = 4n
./b 8 sum = 499999156.515838, time = 0.182354 sec, np = 8n
./b 16 sum = 499999156.515837, time = 0.093795 sec, np = 16n
./b 32 sum = 499999156.515837, time = 0.053239 sec, np = 32n
此外,你應該用了Intel的編譯器吧,這個優化做還是很好的,但是抵不過你調度開銷
。所以一比擴展性你就沒優勢了。

【在 l*******s 的大作中提到】
: 我测的时间不太一样
: mpi perf time / dotp time /perf-dotp time:
: 1 0.485秒 / 0.418秒 /0.067
: 2 0.325秒 / 0.267秒 /0.058
: 4 0.282秒 / 0.233秒 /0.049
: 8 0.225秒 / 0.165秒 /0.060
: 16 0.253秒 / 0.170秒 /0.083
: 32 0.284秒 / 0.188秒 /0.096
: OMP2 perf time / dotp time:
: 1 0.473秒 / 0.460秒 /0.013

j**f
发帖数: 28
50
如果就是dot product你就应该用库,而不是自己写。里面涉及的寄存器,一级缓存,
二级缓存,SIMD, 都不是新手搞得定的。
我收回我的建议,dot product太简单了,SIMD手工优化可以比ATLAS好
https://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/

【在 l*******s 的大作中提到】
: 都说了,能并行的就是一个个的dot product. 怎么增大。能增大早就做了。
m*****p
发帖数: 39
51
我不是intel的cpu,所以不能用icc 18.0.1,我用的是gcc 9.3.0 + avx2 + openmpi 4
.0.6在ubuntu 20.04.2上,不是centos7。實際咝袝r間跟很多因素相關,但我htop看的
結果是mpi需要幾秒鐘調用大量syscalls和kernel space處理,而omp完全是user space
。基本上64線程都單獨使用一個核心,沒有碰撞,這點mpi和omp一樣。
服務器cpu核心越少單核turbo頻率越高。我的單核最高2.7GHz,你的單核最高3.7GHz,
但是全核我的2.2GHz,你的2.1GHz,這個解釋了為啥你的4-8核就到頂峰,而我的16-24
核才到頂峰。
我有機會再用GPU跑跑看。

【在 l*******s 的大作中提到】
: 我用gcc 得到了跟你的类似的结果, 但比intel 慢。
: gcc compiler
: OMP2 perf time / dotp time:
: 1 2.65秒 / 2.64秒
: 2 1.60秒 / 1.59秒
: 4 0.877秒 / 0.870秒
: 8 0.688秒 / 0.680秒
: 16 0.594秒 / 0.587秒
: 32 0.846秒 / 0.837秒
: intel compiler

c*******v
发帖数: 2599
52
程序裡的計算時間的方法似有問題?
不如將malloc放在repeat loop裡面。
最後你再free。在malloc與free之間的時間點不用變。
如此,每次repeat loop裡面取a[k],b[k]計算時,
OS與機器之狀態相對乾淨。
你現在的計算時間方法似乎有兩個缺點:
第一,
因為各種調度算法均有記憶效果(各種調度用的數據結構裡會保留用了多次的東
西,或者most recent計算用到的一些東西)。
這會造成第一次repeat慢。後面可以越來越快(這點應可以簡單測試出來)。
第二,
你下面的計算時間方法不切合真實應用的實際情況。
真實應用時,os與機器應無任務之歷史記憶。

【在 l*******s 的大作中提到】
: 可以请帮忙在你的机器上测试一下MPI 和OMP的reduction的效率?
: 我给你提供code, 帮我测试一下1,2,4,8,16 个processors的运行时间。
: 看看是不是跟我得到的近似。多谢。
: 下面的code 在看到大家的回复后做了一些修改。
: 所以中间帖子里的timing可能不一致。但规律都是一样的
: 这是MPI的code,
: #include
: #include
: #include
: #include

l*******s
发帖数: 7316
53
你的單CPU優化怎么做的?
另外,你试试下面程序。看看單CPU優化或修改掉調度單位管用吗?
c*******v
发帖数: 2599
54
我看還是用庫吧。這個link似乎只考慮了數據已經到了cpu之cache之後的事情。

【在 j**f 的大作中提到】
: 如果就是dot product你就应该用库,而不是自己写。里面涉及的寄存器,一级缓存,
: 二级缓存,SIMD, 都不是新手搞得定的。
: 我收回我的建议,dot product太简单了,SIMD手工优化可以比ATLAS好
: https://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/

c*******v
发帖数: 2599
55
我還是覺得應把
for (j = 0; j < repeat; j++)
放在最前面。不然每次repeat你已經借用了之前一次循環所建立之各種OS狀態。

【在 l*******s 的大作中提到】
: 你的單CPU優化怎么做的?
: 另外,你试试下面程序。看看單CPU優化或修改掉調度單位管用吗?

n******t
发帖数: 4406
56
單CPU就是用blas.像別人說的,這種簡單的手動匯編也不難。
你這個程序我沒看懂想幹嘛,所以不便評論。但是你這個程序原封不動跑了一下,似乎
線程數不等的情況下結果不一致。
sum = 49973945.014750, time = 0.524683 sec, np = 1
sum = 49987748.554291, time = 0.268209 sec, np = 2
sum = 49985725.078290, time = 0.142735 sec, np = 4
sum = 49993121.367840, time = 0.090428 sec, np = 8
sum = 49992154.040189, time = 0.086849 sec, np = 16
sum = 49990524.608644, time = 0.106662 sec, np = 32
一般來說如果是比較複雜的程序用MPI或者OPENMP最好是針對程序的某個sequential
pipeline裏面的一個環節只拆一次,比如說程序有P1,P2,P3三個環節組成,P2必須要P1
完成才能繼續,那P1用MPI這種調度最好只拆一次,你這個拆得有點太細了,overhead
太大。除非你手動調度線程不依賴MPI和OPENMP這種大路貨。
上述情況一般只適用於CPU bound的任務,如果是I/O bound,還要複雜很多。

【在 l*******s 的大作中提到】
: 你的單CPU優化怎么做的?
: 另外,你试试下面程序。看看單CPU優化或修改掉調度單位管用吗?

l*******s
发帖数: 7316
57
结果不一致是因为round off error.
我稍改一下,下面这个程序中round off error不影响结果。
重点是每个repeat循环都跟前一循环的结果相关,
所以不能把reduction集中在一起。
我的目的就是要test reduction peformance。
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 10000;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
double loc_dot = 0;
double sum = 1;
#pragma omp parallel
{
int i, j, k;

double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
#pragma omp for reduction(+: loc_dot)
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
#pragma omp single
{
sum += (loc_dot/(double)(n));
loc_dot =0;
}
}
time += omp_get_wtime();
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %d\n", sum, time, np);
}

return 0;
}
C*****l
发帖数: 1
58
你这个非常适合SIMD的运算,比如INTEL AVX,AVX512,你试用过MKL么?

【在 l*******s 的大作中提到】
: 结果不一致是因为round off error.
: 我稍改一下,下面这个程序中round off error不影响结果。
: 重点是每个repeat循环都跟前一循环的结果相关,
: 所以不能把reduction集中在一起。
: 我的目的就是要test reduction peformance。
: #include
: #include
: #include
: #include
: int main(int argc, char* argv[])

g****t
发帖数: 31659
59
我的理解是。他不完全是想找最优解。主要是用简单的例子测一下openMP之reduction
clause。
看其属于下面哪个范畴:
A. 很烂。无用
B. 有用。但是不知如何选参数以及设计程序
一个重要的问题是,为何求内积这样的简单操作。为何线程增加之后,reduction
clause性能没有继续增加?我猜是调度之overhead太高了。
所以我有个猜想,假如单机用Golang求内积,因为其调度粒度更细。可能更线性些。例
如下面求卷积的代码,可改为内积跑跑看。
https://yourbasic.org/golang/efficient-parallel-computation/
那种语言之并行计算,可以有更线性?
这是个很有意思的问题。
等改天我有空单机单cpu比较下看看。除了go,
也可与java比较下看看。


: 你这个非常适合SIMD的运算,比如INTEL AVX,AVX512,你试用过MKL么?



【在 C*****l 的大作中提到】
: 你这个非常适合SIMD的运算,比如INTEL AVX,AVX512,你试用过MKL么?
l*******s
发帖数: 7316
60
我重新修改了57楼的code,
现在的code 还是模仿dot product, 只不过 element都是compute on the fly.
所以code中没有大的数组,减少cache missing。
我还特意使用了一个sin function,
这样是的新的dot product 跟前面的 dot product的关系更复杂,
以免在element计算中的sum被优化掉。
这样做是为了让大家的注意力集中在reduction上。
请各位帮忙测试一下performance, 或者找到优化方法。多谢。
我的测试结果
OMP
sum = 6992.953984, time = 0.409850 sec, np = 1
sum = 6992.953984, time = 0.270875 sec, np = 2
sum = 6992.953984, time = 0.186024 sec, np = 4
sum = 6992.953984, time = 0.144010 sec, np = 8
sum = 6992.953984, time = 0.115188 sec, np = 16
sum = 6992.953984, time = 0.195485 sec, np = 32
MPI
sum = 6992.953984, time = 0.381701 sec, np = 1
sum = 6992.953984, time = 0.243513 sec, np = 2
sum = 6992.953984, time = 0.158326 sec, np = 4
sum = 6992.953984, time = 0.102489 sec, np = 8
sum = 6992.953984, time = 0.063975 sec, np = 16
sum = 6992.953984, time = 0.044748 sec, np = 32
很明显,MPI的reduction比OMP效率高,但我认为OMP应该能做到比MPI好。

【在 l*******s 的大作中提到】
: 结果不一致是因为round off error.
: 我稍改一下,下面这个程序中round off error不影响结果。
: 重点是每个repeat循环都跟前一循环的结果相关,
: 所以不能把reduction集中在一起。
: 我的目的就是要test reduction peformance。
: #include
: #include
: #include
: #include
: int main(int argc, char* argv[])

l*******s
发帖数: 7316
61
你说的对, 我的主贴就在问reduction效率问题。
可是大家都focus on怎么优化repeated dot-product。
我最初的code设计的不好,太容易被优化了,使得大家都不管我在关心什么。
最初的code中每次dot product 都是完全重复的,数值多是一样。
所以在完全优化后只用做一次dot product 后乘以repeat就可以了。
我重新设计了code。 可能还是成在优化的可能,但已经不明显了。
要求OMP的reduction 比MPI有效应该不是无理要求吧?

reduction

【在 g****t 的大作中提到】
: 我的理解是。他不完全是想找最优解。主要是用简单的例子测一下openMP之reduction
: clause。
: 看其属于下面哪个范畴:
: A. 很烂。无用
: B. 有用。但是不知如何选参数以及设计程序
: 一个重要的问题是,为何求内积这样的简单操作。为何线程增加之后,reduction
: clause性能没有继续增加?我猜是调度之overhead太高了。
: 所以我有个猜想,假如单机用Golang求内积,因为其调度粒度更细。可能更线性些。例
: 如下面求卷积的代码,可改为内积跑跑看。
: https://yourbasic.org/golang/efficient-parallel-computation/

n******t
发帖数: 4406
62
你肯定你的實際運算真的是你下面這個邏輯還是你人爲造出來的case?你這個等於一個
強相關的算法,本來並行效果就不會好的。

【在 l*******s 的大作中提到】
: 结果不一致是因为round off error.
: 我稍改一下,下面这个程序中round off error不影响结果。
: 重点是每个repeat循环都跟前一循环的结果相关,
: 所以不能把reduction集中在一起。
: 我的目的就是要test reduction peformance。
: #include
: #include
: #include
: #include
: int main(int argc, char* argv[])

B********s
发帖数: 675
63
OMP和MPI相差这么大,很可能是CPU affinity的问题。对于Intel OMP,试试
把环境变量KMP_AFFINITY设成scatter。
另外,一般的MPI implementation都对intra node有所优化,大部分是用了shared
memory,所以在你的单机上效率应该和OMP差不多。如果有明显差别,要么是时间计算
不一样(比如是否考虑了各种overhead),要么是scheduler的问题(比如affinity)。

【在 l*******s 的大作中提到】
: 你说的对, 我的主贴就在问reduction效率问题。
: 可是大家都focus on怎么优化repeated dot-product。
: 我最初的code设计的不好,太容易被优化了,使得大家都不管我在关心什么。
: 最初的code中每次dot product 都是完全重复的,数值多是一样。
: 所以在完全优化后只用做一次dot product 后乘以repeat就可以了。
: 我重新设计了code。 可能还是成在优化的可能,但已经不明显了。
: 要求OMP的reduction 比MPI有效应该不是无理要求吧?
:
: reduction

l*******s
发帖数: 7316
64
这种强相关的case很多。比如Krylov linear solver 里面要用到的正交化。
基本上就是这样。每一个dot product用到的element value 都跟前面的dot product
有关。

【在 n******t 的大作中提到】
: 你肯定你的實際運算真的是你下面這個邏輯還是你人爲造出來的case?你這個等於一個
: 強相關的算法,本來並行效果就不會好的。

l*******s
发帖数: 7316
65
我试了修改KMP_AFFINITY, 基本没差别。
export KMP_AFFINITY=scatter

export KMP_AFFINITY scatter
这个命令对吗? 还有其他设置需要调试吗?
改后:
sum = 6992.953984, time = 0.416691 sec, np = 1
sum = 6992.953984, time = 0.270838 sec, np = 2
sum = 6992.953984, time = 0.187582 sec, np = 4
sum = 6992.953984, time = 0.140101 sec, np = 8
sum = 6992.953984, time = 0.118161 sec, np = 16
sum = 6992.953984, time = 0.125198 sec, np = 32
修改前:
sum = 6992.953984, time = 0.409850 sec, np = 1
sum = 6992.953984, time = 0.270875 sec, np = 2
sum = 6992.953984, time = 0.186024 sec, np = 4
sum = 6992.953984, time = 0.144010 sec, np = 8
sum = 6992.953984, time = 0.115188 sec, np = 16
sum = 6992.953984, time = 0.195485 sec, np = 32

【在 B********s 的大作中提到】
: OMP和MPI相差这么大,很可能是CPU affinity的问题。对于Intel OMP,试试
: 把环境变量KMP_AFFINITY设成scatter。
: 另外,一般的MPI implementation都对intra node有所优化,大部分是用了shared
: memory,所以在你的单机上效率应该和OMP差不多。如果有明显差别,要么是时间计算
: 不一样(比如是否考虑了各种overhead),要么是scheduler的问题(比如affinity)。

c*******v
发帖数: 2599
66
你最初那程序,下面這幾行與內積無關吧?就是統計目的?
#pragma omp single
{
sum += (loc_dot/(double)(n));
loc_dot =0;
}

【在 l*******s 的大作中提到】
: 这种强相关的case很多。比如Krylov linear solver 里面要用到的正交化。
: 基本上就是这样。每一个dot product用到的element value 都跟前面的dot product
: 有关。

c*******v
发帖数: 2599
67
絕對速度只是一方面。也許linear scale 問題更重要。
我剛才在我的game laptop上面跑了一下你第一頁的內積程序。
也是thread 8以上後,耗時開始增加。

【在 l*******s 的大作中提到】
: 你说的对, 我的主贴就在问reduction效率问题。
: 可是大家都focus on怎么优化repeated dot-product。
: 我最初的code设计的不好,太容易被优化了,使得大家都不管我在关心什么。
: 最初的code中每次dot product 都是完全重复的,数值多是一样。
: 所以在完全优化后只用做一次dot product 后乘以repeat就可以了。
: 我重新设计了code。 可能还是成在优化的可能,但已经不明显了。
: 要求OMP的reduction 比MPI有效应该不是无理要求吧?
:
: reduction

l*******s
发帖数: 7316
68
export KMP_AFFINITY=compact
这个效果最好。
sum = 6992.953984, time = 0.408360 sec, np = 1
sum = 6992.953984, time = 0.261517 sec, np = 2
sum = 6992.953984, time = 0.172954 sec, np = 4
sum = 6992.953984, time = 0.119487 sec, np = 8
sum = 6992.953984, time = 0.092054 sec, np = 16
sum = 6992.953984, time = 0.113060 sec, np = 32

【在 l*******s 的大作中提到】
: 我试了修改KMP_AFFINITY, 基本没差别。
: export KMP_AFFINITY=scatter
: 或
: export KMP_AFFINITY scatter
: 这个命令对吗? 还有其他设置需要调试吗?
: 改后:
: sum = 6992.953984, time = 0.416691 sec, np = 1
: sum = 6992.953984, time = 0.270838 sec, np = 2
: sum = 6992.953984, time = 0.187582 sec, np = 4
: sum = 6992.953984, time = 0.140101 sec, np = 8

l*******s
发帖数: 7316
69
是的,只是为了避免过度优化。

【在 c*******v 的大作中提到】
: 你最初那程序,下面這幾行與內積無關吧?就是統計目的?
: #pragma omp single
: {
: sum += (loc_dot/(double)(n));
: loc_dot =0;
: }

j**f
发帖数: 28
70

reduction
应该算reduction有用但他的参数不合适,工作量太小不够分
我用atomic把reduction替换以后,小np变差,大np变好.
给for加上 nowait, 大np还可以加速,虽然结果不对但计算量是一样的
np>=16 时间波动很大,不可靠
gcc t2nr.c -fopenmp -o t2nr.x -O2
atomic
sum = 15774.047975, time = 0.478993 sec, np = 1
sum = 15773.415164, time = 0.307828 sec, np = 2
sum = 15773.170634, time = 0.161034 sec, np = 4
sum = 15773.114328, time = 0.097337 sec, np = 8
sum = 15773.023627, time = 0.101083 sec, np = 16
sum = 15773.019270, time = 0.099818 sec, np = 32
reduction
sum = 15774.047975, time = 0.449608 sec, np = 1
sum = 15774.047975, time = 0.251523 sec, np = 2
sum = 15774.047975, time = 0.140971 sec, np = 4
sum = 15774.047975, time = 0.121877 sec, np = 8
sum = 15774.047975, time = 0.127682 sec, np = 16
sum = 15774.047975, time = 0.128808 sec, np = 32
atomic nowait
sum = 15774.047975, time = 0.443214 sec, np = 1
sum = 15750.483609, time = 0.240029 sec, np = 2
sum = 15749.893158, time = 0.130304 sec, np = 4
sum = 15783.550422, time = 0.073210 sec, np = 8
sum = 15553.170144, time = 0.071791 sec, np = 16
sum = 15914.384916, time = 0.060435 sec, np = 32
reduction nowait
sum = 15774.047975, time = 0.447009 sec, np = 1
sum = 15769.952058, time = 0.276017 sec, np = 2
sum = 12160.053164, time = 0.136759 sec, np = 4
sum = 13280.812545, time = 0.104769 sec, np = 8
sum = 14847.901391, time = 0.098864 sec, np = 16
sum = 14218.002954, time = 0.107371 sec, np = 32
icc t2nr.c -qopenmp -o t2nr.x -O2
atomic
sum = 15774.047975, time = 0.263992 sec, np = 1
sum = 15773.459889, time = 0.141759 sec, np = 2
sum = 15773.290539, time = 0.088290 sec, np = 4
sum = 15773.076301, time = 0.058803 sec, np = 8
sum = 15773.076528, time = 0.086343 sec, np = 16
sum = 15773.001462, time = 0.476611 sec, np = 32
reduction
sum = 15774.047975, time = 0.222486 sec, np = 1
sum = 15774.047975, time = 0.126074 sec, np = 2
sum = 15774.047975, time = 0.078066 sec, np = 4
sum = 15774.047975, time = 0.055310 sec, np = 8
sum = 15774.047975, time = 0.059027 sec, np = 16
sum = 15774.047975, time = 0.913732 sec, np = 32
atomic nowait
sum = 15774.047975, time = 0.222162 sec, np = 1
sum = 15680.474010, time = 0.118676 sec, np = 2
sum = 15653.529188, time = 0.070725 sec, np = 4
sum = 15493.733726, time = 0.045788 sec, np = 8
sum = 15771.120010, time = 0.036478 sec, np = 16
sum = 16206.380510, time = 0.054956 sec, np = 32
reduction nowait
sum = 15774.047975, time = 0.221729 sec, np = 1
sum = 14294.544590, time = 0.123898 sec, np = 2
sum = 12886.392032, time = 0.076451 sec, np = 4
sum = 15613.464179, time = 0.054847 sec, np = 8
sum = 15745.009185, time = 0.083885 sec, np = 16
sum = 14903.450378, time = 0.750764 sec, np = 32
Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 10000;
double nn= n*n;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
double sum = 1;
double time = -omp_get_wtime();
#pragma omp parallel
{
int i, j, k;

for (j = 0; j < repeat; j++)
{
double ls;
ls=0.0;
#pragma omp for
for (k = 0; k < sublength; k++)
{
double temp = (sum+ nstart +j +k)/nn;
ls += temp;
}
#pragma omp atomic
sum+=ls;
}
}
time += omp_get_wtime();
printf("sum = %f, time = %f sec, np = %dn", sum, time, np);

return 0;
}

【在 g****t 的大作中提到】
: 我的理解是。他不完全是想找最优解。主要是用简单的例子测一下openMP之reduction
: clause。
: 看其属于下面哪个范畴:
: A. 很烂。无用
: B. 有用。但是不知如何选参数以及设计程序
: 一个重要的问题是,为何求内积这样的简单操作。为何线程增加之后,reduction
: clause性能没有继续增加?我猜是调度之overhead太高了。
: 所以我有个猜想,假如单机用Golang求内积,因为其调度粒度更细。可能更线性些。例
: 如下面求卷积的代码,可改为内积跑跑看。
: https://yourbasic.org/golang/efficient-parallel-computation/

n******t
发帖数: 4406
71
強相關沒有問題,多幾個pipeline而已,問題在於你相關的每個pipeline的size不能改
,而且還是10000這麼小的是一個數。
說實話,我這麼多年實際環境從來沒見過一個case,你那裏那個10000相當的數是不能
改的。Linear solver的分片大小都是可以調的,除非矩陣非常小,which隨便怎麼算都
沒差了。

【在 l*******s 的大作中提到】
: 这种强相关的case很多。比如Krylov linear solver 里面要用到的正交化。
: 基本上就是这样。每一个dot product用到的element value 都跟前面的dot product
: 有关。

n******t
发帖数: 4406
72
你這個算得也實在是慢了點。。我和你一樣的CPU 用OMP,基本上沒改。
sum = 6992.953984, time = 0.153260 sec, np = 1
sum = 6992.953984, time = 0.090700 sec, np = 2
sum = 6992.953984, time = 0.051722 sec, np = 4
sum = 6992.953984, time = 0.042070 sec, np = 8
sum = 6992.953984, time = 0.054564 sec, np = 16
sum = 6992.953984, time = 0.096648 sec, np = 32
問題是即使是空循環;
sum = 1.000000, time = 0.002300 sec, np = 1
sum = 1.000000, time = 0.005608 sec, np = 2
sum = 1.000000, time = 0.011405 sec, np = 4
sum = 1.000000, time = 0.020114 sec, np = 8
sum = 1.000000, time = 0.040158 sec, np = 16
sum = 1.000000, time = 0.055540 sec, np = 32
這個基本上是overhead了,所以你還想要什麼呢?

【在 l*******s 的大作中提到】
: 我试了修改KMP_AFFINITY, 基本没差别。
: export KMP_AFFINITY=scatter
: 或
: export KMP_AFFINITY scatter
: 这个命令对吗? 还有其他设置需要调试吗?
: 改后:
: sum = 6992.953984, time = 0.416691 sec, np = 1
: sum = 6992.953984, time = 0.270838 sec, np = 2
: sum = 6992.953984, time = 0.187582 sec, np = 4
: sum = 6992.953984, time = 0.140101 sec, np = 8

l*******s
发帖数: 7316
73
你说一样的CPU,一样的程序基本没改。
怎么做到速度加倍的?
是compiler不一样? 还是compiling option 不一样?
我想要要让OMP至少不比MPI差。
我的OMP
sum = 6992.953984, time = 0.408360 sec, np = 1
sum = 6992.953984, time = 0.261517 sec, np = 2
sum = 6992.953984, time = 0.172954 sec, np = 4
sum = 6992.953984, time = 0.119487 sec, np = 8
sum = 6992.953984, time = 0.092054 sec, np = 16
sum = 6992.953984, time = 0.113060 sec, np = 32
你的OMP
MPI
sum = 6992.953984, time = 0.381701 sec, np = 1
sum = 6992.953984, time = 0.243513 sec, np = 2
sum = 6992.953984, time = 0.158326 sec, np = 4
sum = 6992.953984, time = 0.102489 sec, np = 8
sum = 6992.953984, time = 0.063975 sec, np = 16
sum = 6992.953984, time = 0.044748 sec, np = 32
l*******s
发帖数: 7316
74
atomic的方法我也试过了。基本上跟reduction clause 差不多。
所以没有提出来讨论。
nowait我也试过了,两个地方都可能有nowait option,但都会引起不正确解。
我还试过用counter来代替barrier or wait(implicit barrier),
效果也不明显。
为了简化问题,我只用reduction clause 来跟MPI_Allreduce 比较。

【在 j**f 的大作中提到】
:
: reduction
: 应该算reduction有用但他的参数不合适,工作量太小不够分
: 我用atomic把reduction替换以后,小np变差,大np变好.
: 给for加上 nowait, 大np还可以加速,虽然结果不对但计算量是一样的
: np>=16 时间波动很大,不可靠
: gcc t2nr.c -fopenmp -o t2nr.x -O2
: atomic
: sum = 15774.047975, time = 0.478993 sec, np = 1
: sum = 15773.415164, time = 0.307828 sec, np = 2

c*******v
发帖数: 2599
75
我把求內積那個程序之n設成int n = 100000;
下面結果看起來就reasonable多了。線程增加到一定程度之後,基本上都是1.2。
不會有性能提高,也不會有性能下降。
數組小的時候,線程大於8個,速度之下降應為各種調度之overhead所引起。
sum = 278.215518, time = 2.877507 sec, np = 1
sum = 278.215518, time = 1.122559 sec, np = 3
sum = 278.215518, time = 1.411872 sec, np = 5
sum = 278.215518, time = 1.200148 sec, np = 7
sum = 278.215518, time = 1.265504 sec, np = 9
sum = 278.215518, time = 1.227077 sec, np = 11
sum = 278.215518, time = 1.225194 sec, np = 13
sum = 278.215518, time = 1.211727 sec, np = 15
sum = 278.215518, time = 1.232751 sec, np = 17
sum = 278.215518, time = 1.224881 sec, np = 19
sum = 278.215518, time = 1.230595 sec, np = 21
sum = 278.215518, time = 1.233759 sec, np = 23
sum = 278.215518, time = 1.226739 sec, np = 25
sum = 278.215518, time = 1.227760 sec, np = 27
sum = 278.215518, time = 1.223140 sec, np = 29
sum = 278.215518, time = 1.220702 sec, np = 31

【在 j**f 的大作中提到】
:
: reduction
: 应该算reduction有用但他的参数不合适,工作量太小不够分
: 我用atomic把reduction替换以后,小np变差,大np变好.
: 给for加上 nowait, 大np还可以加速,虽然结果不对但计算量是一样的
: np>=16 时间波动很大,不可靠
: gcc t2nr.c -fopenmp -o t2nr.x -O2
: atomic
: sum = 15774.047975, time = 0.478993 sec, np = 1
: sum = 15773.415164, time = 0.307828 sec, np = 2

c*******v
发帖数: 2599
76
你測下下面hypothesis是否正確:
sublength太小,導致空循環與下面循環在一個數量級。導致測出來的時間之一個主要
部分
是調度overhead【其和空循環耗時應在一個數量級】。
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}

【在 l*******s 的大作中提到】
: atomic的方法我也试过了。基本上跟reduction clause 差不多。
: 所以没有提出来讨论。
: nowait我也试过了,两个地方都可能有nowait option,但都会引起不正确解。
: 我还试过用counter来代替barrier or wait(implicit barrier),
: 效果也不明显。
: 为了简化问题,我只用reduction clause 来跟MPI_Allreduce 比较。

l*******s
发帖数: 7316
77
我知道sublength太小,引起OMP reduction效率变差。
我认为这不是调度的问题, 因为在MPI code 里有同样的循环
MPI code
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
MPI_Allreduce(&loc_dot, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
sum += (dot/(double)(n));
loc_dot = 0;
OMP code
#pragma omp for reduction(+: loc_dot)
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
#pragma omp single
{
sum += (loc_dot/(double)(n));
loc_dot =0;
}
这两段code实现完全一样的功能。就是每个核累加部分的dotproduct, 然后reduce。
如果两边都取消reduce,performance是一样的。
加上reduce之后,OMP就比MPI差。
注意这两个codes里nstart 和sublength 不一样, 在OMP code 里nstart=0,
sublength=n.
在MPI里sublength=n/np, nstart = my_rank*sublength.
我为了让两个codes计算量相同才吧 +nstart 保留在 temp的计算里。
如果优化OMP code, 可以去掉+nstart
double temp = sin((sum +k +j)/(double)(n));

【在 c*******v 的大作中提到】
: 你測下下面hypothesis是否正確:
: sublength太小,導致空循環與下面循環在一個數量級。導致測出來的時間之一個主要
: 部分
: 是調度overhead【其和空循環耗時應在一個數量級】。
: for (k = 0; k < sublength; k++)
: {
: double temp = sin((sum+ nstart +k +j)/(double)(n));
: loc_dot += (temp * temp);
: }

j**f
发帖数: 28
78
现在的问题就是overhead太大,不是openmp的理想客户.
如果你数组就这么大还想并行,也可以自己写pthread. pthread入手不难,但保证没有
overhead也不容易. pthread要在完全优化单CPU速度的基础上才有意义
openmpi,可能只是把任务分得更严格,碰巧减小了一些miss

【在 l*******s 的大作中提到】
: atomic的方法我也试过了。基本上跟reduction clause 差不多。
: 所以没有提出来讨论。
: nowait我也试过了,两个地方都可能有nowait option,但都会引起不正确解。
: 我还试过用counter来代替barrier or wait(implicit barrier),
: 效果也不明显。
: 为了简化问题,我只用reduction clause 来跟MPI_Allreduce 比较。

c*******v
发帖数: 2599
79
MPI code裡,
int sublength = (int)(ceil((double)(n) / (double)(np)));
其為一變數?
OMP裡, int sublength =n;
sublength為常數?

【在 l*******s 的大作中提到】
: 我知道sublength太小,引起OMP reduction效率变差。
: 我认为这不是调度的问题, 因为在MPI code 里有同样的循环
: MPI code
: for (k = 0; k < sublength; k++)
: {
: double temp = sin((sum+ nstart +k +j)/(double)(n));
: loc_dot += (temp * temp);
: }
: MPI_Allreduce(&loc_dot, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
: sum += (dot/(double)(n));

n******t
发帖数: 4406
80
我vectorize你的loop了,你這個屬於單CPU的很容易vectorize的情況。實際上我後來
發現基本上新點的GCC都可以通過制定m用上avx指令,代碼都不用改。
但是這個並不是關鍵,這種自動並行的線程機制的核心問題都是你控制不了線程的創建
和調度,當然這也是不想手動的代價,不過既然用了別人的東西,就不能說我要多大的
work size就多大了。
具體到MPI和OMP,你看到的差異恰恰是這個你控制不了的情況在這個具體問題上的體現
。MPI應該是開始建立一堆線程就不管了。OMP是自己在編譯器裏面更具需要create和
join的,所以這個overhead在你這個情況下比MPI大。

【在 l*******s 的大作中提到】
: 你说一样的CPU,一样的程序基本没改。
: 怎么做到速度加倍的?
: 是compiler不一样? 还是compiling option 不一样?
: 我想要要让OMP至少不比MPI差。
: 我的OMP
: sum = 6992.953984, time = 0.408360 sec, np = 1
: sum = 6992.953984, time = 0.261517 sec, np = 2
: sum = 6992.953984, time = 0.172954 sec, np = 4
: sum = 6992.953984, time = 0.119487 sec, np = 8
: sum = 6992.953984, time = 0.092054 sec, np = 16

n******t
发帖数: 4406
81
你始終在強調reduce,這東西只是一個high level概念,下面可以有一堆實現,並不是
你去掉了reduce結果變化了,就是reduce的implementation造成的。

【在 l*******s 的大作中提到】
: 我知道sublength太小,引起OMP reduction效率变差。
: 我认为这不是调度的问题, 因为在MPI code 里有同样的循环
: MPI code
: for (k = 0; k < sublength; k++)
: {
: double temp = sin((sum+ nstart +k +j)/(double)(n));
: loc_dot += (temp * temp);
: }
: MPI_Allreduce(&loc_dot, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
: sum += (dot/(double)(n));

c*******v
发帖数: 2599
82
他的mpi code你能跑嗎?
似乎不全?

【在 n******t 的大作中提到】
: 你始終在強調reduce,這東西只是一個high level概念,下面可以有一堆實現,並不是
: 你去掉了reduce結果變化了,就是reduce的implementation造成的。

j**f
发帖数: 28
83
还是比大佬你的差好多,还要点啥?
Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz
gcc t2.c -march=native -ffast-math -fassociative-math -ftree-vectorize -msse
-msse2 -mavx2 -fopenmp -o t2.x -O2 -lm
sum = 6992.953984, time = 0.247078 sec, np = 1
sum = 6992.953984, time = 0.160590 sec, np = 2
sum = 6992.953984, time = 0.085497 sec, np = 4
sum = 6992.953984, time = 0.087919 sec, np = 8
sum = 6992.953984, time = 0.093634 sec, np = 16
sum = 6992.953984, time = 0.108651 sec, np = 32
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx
pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology
nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx
est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe
popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm cpuid_fault
epb invpcid_single pti intel_ppin ssbd ibrs ibpb stibp tpr_shadow vnmi
flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid
cqm xsaveopt cqm_llc cqm_occup_llc dtherm ida arat pln pts flush_l1d

【在 n******t 的大作中提到】
: 你這個算得也實在是慢了點。。我和你一樣的CPU 用OMP,基本上沒改。
: sum = 6992.953984, time = 0.153260 sec, np = 1
: sum = 6992.953984, time = 0.090700 sec, np = 2
: sum = 6992.953984, time = 0.051722 sec, np = 4
: sum = 6992.953984, time = 0.042070 sec, np = 8
: sum = 6992.953984, time = 0.054564 sec, np = 16
: sum = 6992.953984, time = 0.096648 sec, np = 32
: 問題是即使是空循環;
: sum = 1.000000, time = 0.002300 sec, np = 1
: sum = 1.000000, time = 0.005608 sec, np = 2

n******t
发帖数: 4406
84
恩,你能搞的基本上也搞了,差就差了一個avx512f。

msse

【在 j**f 的大作中提到】
: 还是比大佬你的差好多,还要点啥?
: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz
: gcc t2.c -march=native -ffast-math -fassociative-math -ftree-vectorize -msse
: -msse2 -mavx2 -fopenmp -o t2.x -O2 -lm
: sum = 6992.953984, time = 0.247078 sec, np = 1
: sum = 6992.953984, time = 0.160590 sec, np = 2
: sum = 6992.953984, time = 0.085497 sec, np = 4
: sum = 6992.953984, time = 0.087919 sec, np = 8
: sum = 6992.953984, time = 0.093634 sec, np = 16
: sum = 6992.953984, time = 0.108651 sec, np = 32

n******t
发帖数: 4406
85
好像是能跑的。中間有沒有做點小改動不記得了。

不是

【在 c*******v 的大作中提到】
: 他的mpi code你能跑嗎?
: 似乎不全?

n******t
发帖数: 4406
86
樓主想換成openmp,which我可以理解,因爲這東西比mpi透明,寫起來省事。mpi有點
點半自動的效果。
但是這種情況下,你overhead在任務本身分片很小的情況下,就很明顯了。實際上這個
事情在你把單cpu任務開銷優化到足夠小的時候已經一目瞭然了。

【在 j**f 的大作中提到】
: 现在的问题就是overhead太大,不是openmp的理想客户.
: 如果你数组就这么大还想并行,也可以自己写pthread. pthread入手不难,但保证没有
: overhead也不容易. pthread要在完全优化单CPU速度的基础上才有意义
: openmpi,可能只是把任务分得更严格,碰巧减小了一些miss

c*******v
发帖数: 2599
87
用O3試下。
gcc p3.c -fopenmp -lm -O3
比沒有O3快一倍多。

msse

【在 j**f 的大作中提到】
: 还是比大佬你的差好多,还要点啥?
: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz
: gcc t2.c -march=native -ffast-math -fassociative-math -ftree-vectorize -msse
: -msse2 -mavx2 -fopenmp -o t2.x -O2 -lm
: sum = 6992.953984, time = 0.247078 sec, np = 1
: sum = 6992.953984, time = 0.160590 sec, np = 2
: sum = 6992.953984, time = 0.085497 sec, np = 4
: sum = 6992.953984, time = 0.087919 sec, np = 8
: sum = 6992.953984, time = 0.093634 sec, np = 16
: sum = 6992.953984, time = 0.108651 sec, np = 32

c*******v
发帖数: 2599
88
mpi code那sublength是從np求出來的。
是一個變數。如此,似乎他做的並非apple to apple之比較。

【在 n******t 的大作中提到】
: 好像是能跑的。中間有沒有做點小改動不記得了。
:
: 不是

j**f
发帖数: 28
89
看来是CPU太老不支持 avx512f,
加了直接,Illegal instruction
加【在 netghost (Up to Isomorphism) 的大作中提到: 】
n******t
发帖数: 4406
90
他都上那一堆開關了,這個O3啥的他顯然試過了。

【在 c*******v 的大作中提到】
: 用O3試下。
: gcc p3.c -fopenmp -lm -O3
: 比沒有O3快一倍多。
:
: msse

n******t
发帖数: 4406
91
對的,稍微老了一點。但是idea没差,这种代码稍微优化一下,立刻就看出overhead在
哪里了。
你可以把march=native那个去了试试,gcc加那个有时候会发神经。

【在 j**f 的大作中提到】
: 看来是CPU太老不支持 avx512f,
: 加了直接,Illegal instruction
: 加【在 netghost (Up to Isomorphism) 的大作中提到: 】

n******t
发帖数: 4406
92
没本质区别,就是手动算一个分片。
MPI这东西我上一次用至少是20年前了, 结果基本上好像也没什么变化。
但是这种东西,自己pthread create一下很难吗,那真是一个手艺学了可以用30年。

【在 c*******v 的大作中提到】
: mpi code那sublength是從np求出來的。
: 是一個變數。如此,似乎他做的並非apple to apple之比較。

c*******v
发帖数: 2599
93
-Ofast比-O3又快很多。

【在 n******t 的大作中提到】
: 他都上那一堆開關了,這個O3啥的他顯然試過了。
c*******v
发帖数: 2599
94
loop次數不一樣。乘法和加法,sin次數不同了。
OMP loop次數為n。
MPI程序 loop數等於int sublength = (int)(ceil((double)(n) / (double)(np)));
np=8時,sin少算8次。這是兩個不同的程序了。

【在 n******t 的大作中提到】
: 没本质区别,就是手动算一个分片。
: MPI这东西我上一次用至少是20年前了, 结果基本上好像也没什么变化。
: 但是这种东西,自己pthread create一下很难吗,那真是一个手艺学了可以用30年。

j**f
发帖数: 28
95
用O3要快一点.
你把编译指令写code里了吗? 只用 gcc p3.c -fopenmp -lm -O3 直接打回原形,要1.3 秒
sum = 6992.953984, time = 0.216588 sec, np = 1
sum = 6992.953984, time = 0.118749 sec, np = 2
sum = 6992.953984, time = 0.104176 sec, np = 4
sum = 6992.953984, time = 0.082472 sec, np = 8
sum = 6992.953984, time = 0.092022 sec, np = 16
sum = 6992.953984, time = 0.109844 sec, np = 32

【在 c*******v 的大作中提到】
: 用O3試下。
: gcc p3.c -fopenmp -lm -O3
: 比沒有O3快一倍多。
:
: msse

n******t
发帖数: 4406
96
你这个显然别人也试过了,他是在有目的的调开关了。

【在 c*******v 的大作中提到】
: -Ofast比-O3又快很多。
c*******v
发帖数: 2599
97
沒有。我就直接用他的code。改了改n, repeat。
外面加了總的loop選不同的thread。

3 秒

【在 j**f 的大作中提到】
: 用O3要快一点.
: 你把编译指令写code里了吗? 只用 gcc p3.c -fopenmp -lm -O3 直接打回原形,要1.3 秒
: sum = 6992.953984, time = 0.216588 sec, np = 1
: sum = 6992.953984, time = 0.118749 sec, np = 2
: sum = 6992.953984, time = 0.104176 sec, np = 4
: sum = 6992.953984, time = 0.082472 sec, np = 8
: sum = 6992.953984, time = 0.092022 sec, np = 16
: sum = 6992.953984, time = 0.109844 sec, np = 32

n******t
发帖数: 4406
98
不要纠结这些和讨论无关的东西。边界不会影响速度的。

【在 c*******v 的大作中提到】
: loop次數不一樣。乘法和加法,sin次數不同了。
: OMP loop次數為n。
: MPI程序 loop數等於int sublength = (int)(ceil((double)(n) / (double)(np)));
: np=8時,sin少算8次。這是兩個不同的程序了。

l*******s
发帖数: 7316
99
为什么不能确定是reduce的implementation造成的。
下面是我去掉reduce 以后测的时间。
这些结果当然是错误的,但运行时间是除了reduce之外的时间。
sum = 6992.953984, time = 0.413514 sec, np = 1
sum = 4097.978213, time = 0.248612 sec, np = 2
sum = 1967.810634, time = 0.152884 sec, np = 4
sum = 1121.367963, time = 0.091141 sec, np = 8
sum = 567.774710, time = 0.052051 sec, np = 16
sum = 113.105499, time = 0.027059 sec, np = 32
在我的下面的code里有一个假的reduce function.
如果能实施一个高效的reduce function, 我的问题就解决了。
#include
#include
#include
#include
double OMP_Allreduce_dsum0(double loc_sum, int tid, int np)
{
return loc_sum;
}
int main(int argc, char* argv[])
{
int n = 10000;
int repeat = 10000;
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);

int nstart =0;
int sublength =n;
#pragma omp parallel
{
int i, j, k;
int my_rank = omp_get_thread_num();
double loc_dot = 0;
double sum = 1;

double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
#pragma omp for nowait
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
double dot = OMP_Allreduce_dsum0(loc_dot, my_rank, np);
sum += (dot/(double)(n));
loc_dot =0;
}
time += omp_get_wtime();
sum = OMP_Allreduce_dsum0(sum, my_rank, np);
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %dn", sum, time, np);
}

return 0;
}

【在 n******t 的大作中提到】
: 你始終在強調reduce,這東西只是一個high level概念,下面可以有一堆實現,並不是
: 你去掉了reduce結果變化了,就是reduce的implementation造成的。

n******t
发帖数: 4406
100
没必要O3,关键是要向量化。
他这个代码说实话很无聊,90%的时间其实是在给数组赋值,dot product不花什么时间。

3 秒

【在 j**f 的大作中提到】
: 用O3要快一点.
: 你把编译指令写code里了吗? 只用 gcc p3.c -fopenmp -lm -O3 直接打回原形,要1.3 秒
: sum = 6992.953984, time = 0.216588 sec, np = 1
: sum = 6992.953984, time = 0.118749 sec, np = 2
: sum = 6992.953984, time = 0.104176 sec, np = 4
: sum = 6992.953984, time = 0.082472 sec, np = 8
: sum = 6992.953984, time = 0.092022 sec, np = 16
: sum = 6992.953984, time = 0.109844 sec, np = 32

n******t
发帖数: 4406
101
你这个情况实际上还比我之前说的简单。
这么说吧,你把这一行:
double t, time = -omp_get_wtime();
移到你mpi程序的main开始(before MPI_INIT),再run一下把结果贴上来,这样你该明
白了。

【在 l*******s 的大作中提到】
: 为什么不能确定是reduce的implementation造成的。
: 下面是我去掉reduce 以后测的时间。
: 这些结果当然是错误的,但运行时间是除了reduce之外的时间。
: sum = 6992.953984, time = 0.413514 sec, np = 1
: sum = 4097.978213, time = 0.248612 sec, np = 2
: sum = 1967.810634, time = 0.152884 sec, np = 4
: sum = 1121.367963, time = 0.091141 sec, np = 8
: sum = 567.774710, time = 0.052051 sec, np = 16
: sum = 113.105499, time = 0.027059 sec, np = 32
: 在我的下面的code里有一个假的reduce function.

j**f
发帖数: 28
102
被O3坑过不敢随便. Ofast和O3 差不多
-march=native 去掉关系不大
用O3/Ofast 感觉 np=1 的时间变动加大 0.21-0.29 sec, 不如O2, 0.24 sec放心. 还
好sum一样

【在 c*******v 的大作中提到】
: -Ofast比-O3又快很多。
c*******v
发帖数: 2599
103
np=8時。你的原始程序,MPI循環為sublength=10000/8=1250次。
OMP循環為10000次?
這怎麼比較呢。

【在 l*******s 的大作中提到】
: 为什么不能确定是reduce的implementation造成的。
: 下面是我去掉reduce 以后测的时间。
: 这些结果当然是错误的,但运行时间是除了reduce之外的时间。
: sum = 6992.953984, time = 0.413514 sec, np = 1
: sum = 4097.978213, time = 0.248612 sec, np = 2
: sum = 1967.810634, time = 0.152884 sec, np = 4
: sum = 1121.367963, time = 0.091141 sec, np = 8
: sum = 567.774710, time = 0.052051 sec, np = 16
: sum = 113.105499, time = 0.027059 sec, np = 32
: 在我的下面的code里有一个假的reduce function.

B********s
发帖数: 675
104
你的code版本太多,估计大家都没法follow了。
看不是不reduce的问题,比较下面两个:
1. 用OMP reduce
2. 不用OMP reduce, allocate一个数组,手动的让每个thread reduce local
variable到对应于rank的element
看看这两个时间有没有差异

【在 l*******s 的大作中提到】
: 为什么不能确定是reduce的implementation造成的。
: 下面是我去掉reduce 以后测的时间。
: 这些结果当然是错误的,但运行时间是除了reduce之外的时间。
: sum = 6992.953984, time = 0.413514 sec, np = 1
: sum = 4097.978213, time = 0.248612 sec, np = 2
: sum = 1967.810634, time = 0.152884 sec, np = 4
: sum = 1121.367963, time = 0.091141 sec, np = 8
: sum = 567.774710, time = 0.052051 sec, np = 16
: sum = 113.105499, time = 0.027059 sec, np = 32
: 在我的下面的code里有一个假的reduce function.

l*******m
发帖数: 1096
105
既然不是自己实现具体细节, 你试试不同的openmp reduction的实现。目前你的实现是
#pragma omp single
可以换成master, critical, atomic,。。。还有很多。

【在 l*******s 的大作中提到】
: 没找到更合适的版面讨论这个问题,就在这里问吧.
: 我发现OpenMP的reduction效率很差,做同样的两个向量的内积,MPI要比OpenMP还快。
: MPI是分布内存,需要信息交换才能完成reduction。 结果比使用共享内存的OpenMP还
: 快。
: 这说明OpenMP的reduction没有搞好。我不知道是我使用的系统的问题还是普遍问题。
: 有人有类似的经验吗? 怎么解决?
: 我提供了一个code,然后再大家的反馈后做了修改。 现在把code也帖再这里。
: 省得大家爬楼。
: 现在的code 还是模仿dot product, 只不过 element都是compute on the fly.
: 所以code中没有大的数组,减少cache missing。

B********s
发帖数: 675
106
如果只看楼主最初的code,前面不少人给出结论了:
OpenMP的timer比MPI的多了threading的overhead,所以scaling会差一些。
对于OpenMP,即便用了thread pool,每次outer loop都还是会重新wake up thread和
让thread sleep,这个overhead随着np增大会越来越明显。
而对于MPI,楼主忽略了初始化的时间,而mpi code的outer loop并没有这些overhead
,只有MPI_Allreduce的同步略微有些影响。
楼主可以试试Intel OpenMP的这个环境变量:
KMP_BLOCKTIME
设置成infinite防止thread sleep,应该可以减少每次outer loop的overhead

【在 B********s 的大作中提到】
: 你的code版本太多,估计大家都没法follow了。
: 看不是不reduce的问题,比较下面两个:
: 1. 用OMP reduce
: 2. 不用OMP reduce, allocate一个数组,手动的让每个thread reduce local
: variable到对应于rank的element
: 看看这两个时间有没有差异

c*******v
发帖数: 2599
107
我剛測了下。
這個link給的技術求dotproduct效果很穩定。儘管不是特別明顯。
另外就是math.h的sin極其昂貴。
sin dominate計算時間,會導致會看不出來多少提高。
"
What ATLAS did, and what I copied in the Unrolled version, is this:
dot1 += A[i] * B[i];
dot2 += A[i + 1] * B[i + 1];
dot3 += A[i + 2] * B[i + 2];
dot4 += A[i + 3] * B[i + 3];
This meant there was no longer any dependency between statements, and the
CPU’s out of order execution engine could run all four of these as soon as
the data was available. In a sense, the CPU is vectorizing loops on the fly.
"

【在 j**f 的大作中提到】
: 如果就是dot product你就应该用库,而不是自己写。里面涉及的寄存器,一级缓存,
: 二级缓存,SIMD, 都不是新手搞得定的。
: 我收回我的建议,dot product太简单了,SIMD手工优化可以比ATLAS好
: https://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/

l*******s
发帖数: 7316
108
MPI是把memory当分布式处理。每个核循環1250次.
OMP8核一起循環10000次, 其中每核循环1250次.
每核工作量是一样的。

【在 c*******v 的大作中提到】
: np=8時。你的原始程序,MPI循環為sublength=10000/8=1250次。
: OMP循環為10000次?
: 這怎麼比較呢。

j**f
发帖数: 28
109
算是看懂了这篇文章, 认识到了为什么不该用atomic
https://coderwall.com/p/gocbhg/openmp-improve-reduction-techniques
thread array with for nowait 可以比 reduction 好点点, sum差异应该是round
error
reduction
sum = 6992.953984, time = 0.219194 sec, np = 1
sum = 6992.953984, time = 0.117103 sec, np = 2
sum = 6992.953984, time = 0.105183 sec, np = 4
sum = 6992.953984, time = 0.078228 sec, np = 8
sum = 6992.953984, time = 0.087476 sec, np = 16
sum = 6992.953984, time = 0.343639 sec, np = 32
thread array with for nowait
sum = 6992.953984, time = 0.210598 sec, np = 1
sum = 6992.459277, time = 0.113893 sec, np = 2
sum = 6992.410753, time = 0.081251 sec, np = 4
sum = 6992.276900, time = 0.064732 sec, np = 8
sum = 6992.321792, time = 0.061637 sec, np = 16
sum = 6992.545499, time = 0.083507 sec, np = 32
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int n = 10000;
int repeat = 10000;
int np = 1;
if (argc > 1) {
np = atoi(argv[1]);
}
omp_set_num_threads(np);
int nstart = 0;
int sublength = n;
double sum = 1;
double lca[np];
#pragma omp parallel default(none) shared(lca,np,sum,nstart,sublength,n,
repeat)
{
double loc_dot;
int i, j, k;
int tid = omp_get_thread_num();
double time = -omp_get_wtime();
int chunk = n / np;
for (j = 0; j < repeat; j++) {
loc_dot = 0.0;
#pragma omp for schedule(static, chunk) nowait
for (k = 0; k < sublength; k++) {
double temp = sin((sum + nstart + k + j) / (double)(n));
loc_dot += (temp * temp);
}
lca[tid] = loc_dot / (double)(n);
#pragma omp single
for (k = 0; k < np; k++) {
sum += lca[k];
}
}
time += omp_get_wtime();
#pragma omp single nowait
printf("sum = %f, time = %f sec, np = %dn", sum, time, np);
}
return 0;
}

msse

【在 j**f 的大作中提到】
: 还是比大佬你的差好多,还要点啥?
: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz
: gcc t2.c -march=native -ffast-math -fassociative-math -ftree-vectorize -msse
: -msse2 -mavx2 -fopenmp -o t2.x -O2 -lm
: sum = 6992.953984, time = 0.247078 sec, np = 1
: sum = 6992.953984, time = 0.160590 sec, np = 2
: sum = 6992.953984, time = 0.085497 sec, np = 4
: sum = 6992.953984, time = 0.087919 sec, np = 8
: sum = 6992.953984, time = 0.093634 sec, np = 16
: sum = 6992.953984, time = 0.108651 sec, np = 32

l*******s
发帖数: 7316
110
thread array 在sum之前需要保证每个thread都已经赋值了。
这样就要加一个barrier,估计比atomic还差。

【在 j**f 的大作中提到】
: 算是看懂了这篇文章, 认识到了为什么不该用atomic
: https://coderwall.com/p/gocbhg/openmp-improve-reduction-techniques
: thread array with for nowait 可以比 reduction 好点点, sum差异应该是round
: error
: reduction
: sum = 6992.953984, time = 0.219194 sec, np = 1
: sum = 6992.953984, time = 0.117103 sec, np = 2
: sum = 6992.953984, time = 0.105183 sec, np = 4
: sum = 6992.953984, time = 0.078228 sec, np = 8
: sum = 6992.953984, time = 0.087476 sec, np = 16

l*******s
发帖数: 7316
111
下面总时间和loop时间都给出了, 并不影响结果。
OMP
np = 1 sum = 6992.953984, loop time = 0.408236 sec, total time = 0.412634
np = 2 sum = 6992.953984, loop time = 0.269403 sec, total time = 0.273937
np = 4 sum = 6992.953984, loop time = 0.184081 sec, total time = 0.188961
np = 8 sum = 6992.953984, loop time = 0.142919 sec, total time = 0.147943
np = 16 sum = 6992.953984, loop time = 0.156257 sec, total time = 0.162349
np = 32 sum = 6992.953984, loop time = 0.180854 sec, total time = 0.188388
MPI
np = 1 sum = 6992.953984, loop time = 0.388432 sec, total time = 0.398434
np = 2 sum = 6992.953984, loop time = 0.250379 sec, total time = 0.261760
np = 4 sum = 6992.953984, loop time = 0.157185 sec, total time = 0.170362
np = 8 sum = 6992.953984, loop time = 0.101224 sec, total time = 0.117841
np = 16 sum = 6992.953984, loop time = 0.061332 sec, total time = 0.084613
np = 32 sum = 6992.953984, loop time = 0.043481 sec, total time = 0.086247

【在 n******t 的大作中提到】
: 你这个情况实际上还比我之前说的简单。
: 这么说吧,你把这一行:
: double t, time = -omp_get_wtime();
: 移到你mpi程序的main开始(before MPI_INIT),再run一下把结果贴上来,这样你该明
: 白了。

n******t
发帖数: 4406
112

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
看這裏,明白了沒?
该明

【在 l*******s 的大作中提到】
: 下面总时间和loop时间都给出了, 并不影响结果。
: OMP
: np = 1 sum = 6992.953984, loop time = 0.408236 sec, total time = 0.412634
: np = 2 sum = 6992.953984, loop time = 0.269403 sec, total time = 0.273937
: np = 4 sum = 6992.953984, loop time = 0.184081 sec, total time = 0.188961
: np = 8 sum = 6992.953984, loop time = 0.142919 sec, total time = 0.147943
: np = 16 sum = 6992.953984, loop time = 0.156257 sec, total time = 0.162349
: np = 32 sum = 6992.953984, loop time = 0.180854 sec, total time = 0.188388
: MPI
: np = 1 sum = 6992.953984, loop time = 0.388432 sec, total time = 0.398434

j**f
发帖数: 28
113
在single前加 barrier, 可以消除sum差异, 之前的确没有同步
#pragma omp barrier
#pragma omp single
thread array with for nowait and barrier before single
可以做得比reduction 好一点儿, 也可以差一点
reduction
sum = 6992.953984, time = 0.218412 sec, np = 1
sum = 6992.953984, time = 0.120420 sec, np = 2
sum = 6992.953984, time = 0.090650 sec, np = 4
sum = 6992.953984, time = 0.081235 sec, np = 8
sum = 6992.953984, time = 0.092800 sec, np = 16
sum = 6992.953984, time = 0.107621 sec, np = 32
thread array with for nowait and barrier before single
sum = 6992.953984, time = 0.208075 sec, np = 1
sum = 6992.953984, time = 0.118550 sec, np = 2
sum = 6992.953984, time = 0.078497 sec, np = 4
sum = 6992.953984, time = 0.082000 sec, np = 8
sum = 6992.953984, time = 0.089179 sec, np = 16
sum = 6992.953984, time = 0.097233 sec, np = 32
another run
reduction
sum = 6992.953984, time = 0.212445 sec, np = 1
sum = 6992.953984, time = 0.116725 sec, np = 2
sum = 6992.953984, time = 0.096100 sec, np = 4
sum = 6992.953984, time = 0.080756 sec, np = 8
sum = 6992.953984, time = 0.095057 sec, np = 16
sum = 6992.953984, time = 0.107498 sec, np = 32
thread array with for nowait and barrier before single
sum = 6992.953984, time = 0.217186 sec, np = 1
sum = 6992.953984, time = 0.118578 sec, np = 2
sum = 6992.953984, time = 0.106688 sec, np = 4
sum = 6992.953984, time = 0.079233 sec, np = 8
sum = 6992.953984, time = 0.084670 sec, np = 16
sum = 6992.953984, time = 0.146309 sec, np = 32

【在 l*******s 的大作中提到】
: thread array 在sum之前需要保证每个thread都已经赋值了。
: 这样就要加一个barrier,估计比atomic还差。

c*******v
发帖数: 2599
114
為何你的np=1比我還要慢?我這個game laptop四年前800刀買的。
timeX = 180326,sum = 6992.953984, time = 0.180324 sec, np = 1
難道說碰到了神機?

【在 j**f 的大作中提到】
: 在single前加 barrier, 可以消除sum差异, 之前的确没有同步
: #pragma omp barrier
: #pragma omp single
: thread array with for nowait and barrier before single
: 可以做得比reduction 好一点儿, 也可以差一点
: reduction
: sum = 6992.953984, time = 0.218412 sec, np = 1
: sum = 6992.953984, time = 0.120420 sec, np = 2
: sum = 6992.953984, time = 0.090650 sec, np = 4
: sum = 6992.953984, time = 0.081235 sec, np = 8

j**f
发帖数: 28
115
Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz. CPU First Seen on Charts: Q4 2014.
No avx512f, no turbo

【在 c*******v 的大作中提到】
: 為何你的np=1比我還要慢?我這個game laptop四年前800刀買的。
: timeX = 180326,sum = 6992.953984, time = 0.180324 sec, np = 1
: 難道說碰到了神機?

c*******v
发帖数: 2599
116
我的是 Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz
樓主花了0.4秒for np=1。也許是gcc flag沒弄對吧。

2014.

【在 j**f 的大作中提到】
: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz. CPU First Seen on Charts: Q4 2014.
: No avx512f, no turbo

B********s
发帖数: 675
117
很简单,你的timer只算了一次MPI processes初始化时间,但是算了10000次OMP的
threads wakeup/sleep时间。
如果要做fair comparison,把n改成100000000,repeat改成1
你再看看MPI和OMP的scaling

【在 l*******s 的大作中提到】
: 下面总时间和loop时间都给出了, 并不影响结果。
: OMP
: np = 1 sum = 6992.953984, loop time = 0.408236 sec, total time = 0.412634
: np = 2 sum = 6992.953984, loop time = 0.269403 sec, total time = 0.273937
: np = 4 sum = 6992.953984, loop time = 0.184081 sec, total time = 0.188961
: np = 8 sum = 6992.953984, loop time = 0.142919 sec, total time = 0.147943
: np = 16 sum = 6992.953984, loop time = 0.156257 sec, total time = 0.162349
: np = 32 sum = 6992.953984, loop time = 0.180854 sec, total time = 0.188388
: MPI
: np = 1 sum = 6992.953984, loop time = 0.388432 sec, total time = 0.398434

n******t
发帖数: 4406
118
確切來說,是OMP的thread management是黑盒,創建了多少次,怎麼wakeup都是
implementation dependent的。具體他這個情況,我倒是覺得wakeup時間不算主要的,
其實就是他沒算建立線程的時間,這個在他自己覺得沒區別的測試裏面已經很清楚了:
MPI:
np = 32 sum = 6992.953984, loop time = 0.043481 sec, total time = 0.086247
這總時間裏面有一半在create線程,沒啥好叫的。

【在 B********s 的大作中提到】
: 很简单,你的timer只算了一次MPI processes初始化时间,但是算了10000次OMP的
: threads wakeup/sleep时间。
: 如果要做fair comparison,把n改成100000000,repeat改成1
: 你再看看MPI和OMP的scaling

j**f
发帖数: 28
119
change
to
#pragma omp barrier
#pragma omp master
could speed up at np>=4,
sum = 6992.953984, time = 0.231183 sec, np = 1
sum = 6992.977972, time = 0.114765 sec, np = 2
sum = 6992.913879, time = 0.069948 sec, np = 4
sum = 6992.896652, time = 0.054346 sec, np = 8
sum = 6992.866811, time = 0.044499 sec, np = 16
sum = 6992.232058, time = 0.052284 sec, np = 32
the time are closer to openmpi now.
however another barrier is necessary to make the sum right. It slow it down,
but still faster than reduction at larger np.
#pragma omp barrier
#pragma omp master
for (k = 0; k < np; k++) {
sum += lca[k];
}
#pragma omp barrier
sum = 6992.953984, time = 0.213375 sec, np = 1
sum = 6992.953984, time = 0.117005 sec, np = 2
sum = 6992.953984, time = 0.093248 sec, np = 4
sum = 6992.953984, time = 0.064866 sec, np = 8
sum = 6992.953984, time = 0.070267 sec, np = 16
sum = 6992.953984, time = 0.078379 sec, np = 32
n******t
发帖数: 4406
120
沒什麼大的意義,樓主一定要把算法設計成每隔CPU喂不飽還順序執行這件事情是無解
的。

【在 j**f 的大作中提到】
: change
: to
: #pragma omp barrier
: #pragma omp master
: could speed up at np>=4,
: sum = 6992.953984, time = 0.231183 sec, np = 1
: sum = 6992.977972, time = 0.114765 sec, np = 2
: sum = 6992.913879, time = 0.069948 sec, np = 4
: sum = 6992.896652, time = 0.054346 sec, np = 8
: sum = 6992.866811, time = 0.044499 sec, np = 16

n******t
发帖数: 4406
121
Moore' law早就失效了。都是在拼core的數目。server CPU的優勢在於core多,cache
多,帶寬大。問題是這些東西都不是像之前升級cpu直接就變快的,core再多不會用也
沒效果。
單core性能,你的比他強,而且他還沒有turbo,這樣等於是3.5Ghz在和2.4Ghz的比。
這還不算樓主這個程序任務一個就一點點,server cpu的那些個cache也沒啥用。

【在 c*******v 的大作中提到】
: 為何你的np=1比我還要慢?我這個game laptop四年前800刀買的。
: timeX = 180326,sum = 6992.953984, time = 0.180324 sec, np = 1
: 難道說碰到了神機?

j**f
发帖数: 28
122
我在自己玩,顺便学点东西 ^_^
1. for loop 要能加nowiat
np 太多的情况下
2. atomic 靠不住
3. single 不如 barrier/ master/ barrier 可靠
4. 怎么把openmp写成openmpi一样分块明确. 不用 omp for; 时间跟 for nowait 差不
多.
多谢指点.

【在 n******t 的大作中提到】
: 沒什麼大的意義,樓主一定要把算法設計成每隔CPU喂不飽還順序執行這件事情是無解
: 的。

l*******m
发帖数: 1096
123
所以gpu那么火是必然的。现在只要run session比较长,用Python写,jit优化一下效
率还是很高的。

:Moore' law早就失效了。都是在拼core的數目。server CPU的優勢在於core多,
cache
:多,帶寬大。問題是這些東西都不是像之前升級cpu直接就變快的,core再多不會用也
j**f
发帖数: 28
124
taichi 看写法感觉很类似. 是不是也是jit差不多大的技术,只是更关注于图像?
https://github.com/taichi-dev/taichi

用也

【在 l*******m 的大作中提到】
: 所以gpu那么火是必然的。现在只要run session比较长,用Python写,jit优化一下效
: 率还是很高的。
:
: :Moore' law早就失效了。都是在拼core的數目。server CPU的優勢在於core多,
: cache
: :多,帶寬大。問題是這些東西都不是像之前升級cpu直接就變快的,core再多不會用也

n******t
发帖数: 4406
125
GPU火是intel自己被自己限制住了。其實nvidia能塞那麼多core是因爲每個shader非常
簡單。但是Intel 這種CPU賣太好的只能往SSE這個方向搞。

用也

【在 l*******m 的大作中提到】
: 所以gpu那么火是必然的。现在只要run session比较长,用Python写,jit优化一下效
: 率还是很高的。
:
: :Moore' law早就失效了。都是在拼core的數目。server CPU的優勢在於core多,
: cache
: :多,帶寬大。問題是這些東西都不是像之前升級cpu直接就變快的,core再多不會用也

n******t
发帖数: 4406
126
openmp這種東西只是接口,實現上面很難控制。玩玩和一般應用還是可以,serious的
計算我覺得沒啥優勢。
MPI本來就是用來做科學計算的,一來就fork一堆這個對general的應用不現實。所以
openmp不走那個路線也可以理解。

【在 j**f 的大作中提到】
: 我在自己玩,顺便学点东西 ^_^
: 1. for loop 要能加nowiat
: np 太多的情况下
: 2. atomic 靠不住
: 3. single 不如 barrier/ master/ barrier 可靠
: 4. 怎么把openmp写成openmpi一样分块明确. 不用 omp for; 时间跟 for nowait 差不
: 多.
: 多谢指点.

l*******s
发帖数: 7316
127
多谢各位回复。 我找到目前最佳reduce了。
OMP performance:
np = 1 sum = 6992.953984, loop time = 0.246376 sec, total time = 0.250978
np = 2 sum = 6992.953984, loop time = 0.160334 sec, total time = 0.164939
np = 4 sum = 6992.953984, loop time = 0.105096 sec, total time = 0.110154
np = 8 sum = 6992.953984, loop time = 0.074775 sec, total time = 0.080252
np = 16 sum = 6992.953984, loop time = 0.049352 sec, total time = 0.057083
np = 32 sum = 6992.953984, loop time = 0.101747 sec, total time = 0.109425
我的最佳redcution 实施
#include
#include
#include
#include
double darr[2][32];
int nreduce=0;
#pragma omp threadprivate(nreduce)
double OMP_Allreduce_dsum(double loc_dot,int tid,int np)
{
darr[nreduce][tid]=loc_dot;
#pragma omp barrier
double dsum =0;
int i;
for (i=0; i {
dsum += darr[nreduce][i];
}
nreduce=1-nreduce;
return dsum;
}
int main(int argc, char* argv[])
{
int np = 1;
if (argc > 1)
{
np = atoi(argv[1]);
}
omp_set_num_threads(np);
double ttime = -omp_get_wtime();
int n = 10000;
int repeat = 10000;

int nstart =0;
int sublength =n;
#pragma omp parallel
{
int i, j, k;
int tid = omp_get_thread_num();

double sum = 1;
double time = -omp_get_wtime();
for (j = 0; j < repeat; j++)
{
double loc_dot = 0;
#pragma omp for nowait
for (k = 0; k < sublength; k++)
{
double temp = sin((sum+ nstart +k +j)/(double)(n));
loc_dot += (temp * temp);
}
double dot =OMP_Allreduce_dsum(loc_dot,tid,np);
sum +=(dot/(double)(n));
}
time += omp_get_wtime();
#pragma omp single
ttime += omp_get_wtime();
#pragma omp single nowait
printf("np = %d sum = %f, loop time = %f sec, total time = %f n", np
, sum, time, ttime);
}

return 0;
}
c*******v
发帖数: 2599
128
在我的機器上比你原來的代碼慢啊。
這個新代碼在我機器上,最快的仍然是np=4.但是要0.06秒。

【在 l*******s 的大作中提到】
: 多谢各位回复。 我找到目前最佳reduce了。
: OMP performance:
: np = 1 sum = 6992.953984, loop time = 0.246376 sec, total time = 0.250978
: np = 2 sum = 6992.953984, loop time = 0.160334 sec, total time = 0.164939
: np = 4 sum = 6992.953984, loop time = 0.105096 sec, total time = 0.110154
: np = 8 sum = 6992.953984, loop time = 0.074775 sec, total time = 0.080252
: np = 16 sum = 6992.953984, loop time = 0.049352 sec, total time = 0.057083
: np = 32 sum = 6992.953984, loop time = 0.101747 sec, total time = 0.109425
: 我的最佳redcution 实施
: #include

B********s
发帖数: 675
129
在俺这儿也是比老代码慢
这个新代码就是用了double buffer手动reduce,俺是看不出来有啥优势。
还是楼主改了编译选项?
PS, 你的机器是4核,所以np=4最快也是预料之中

【在 c*******v 的大作中提到】
: 在我的機器上比你原來的代碼慢啊。
: 這個新代碼在我機器上,最快的仍然是np=4.但是要0.06秒。

c*******v
发帖数: 2599
130
他這個程序主要時間其實都在1萬次sin計算。別的時間極小。
mpi之sin計算會不會有trick?

【在 B********s 的大作中提到】
: 在俺这儿也是比老代码慢
: 这个新代码就是用了double buffer手动reduce,俺是看不出来有啥优势。
: 还是楼主改了编译选项?
: PS, 你的机器是4核,所以np=4最快也是预料之中

l*******s
发帖数: 7316
131
每次reduce由原来的2次sync变成1次。
原来在omp for reduction 结束是要sync一次(implicit barrier)
在omp single 结束是要sync一次(implicit barrier)
有人建议用omp master, 结束后加一个barrier, 效果基本是一样的。
新的code,只在所有thread 给shared数组darr赋值后有一个barrier,
其他都用重复计算代替barrier。
这样没有omp master 或 omp single.
所有线程create以后就不休息,一直active。
我的compiling flags是这样的
icc -O3 -qopenmp -march=native -ffast-math reduction_mpi.c -o reduction_mpi
-lm

【在 B********s 的大作中提到】
: 在俺这儿也是比老代码慢
: 这个新代码就是用了double buffer手动reduce,俺是看不出来有啥优势。
: 还是楼主改了编译选项?
: PS, 你的机器是4核,所以np=4最快也是预料之中

c*******v
发帖数: 2599
132
np=4基本上已經最優了。我所需時間為0.051。
np=1時,我把n設成2500。所需時間為0.047。
單線程算2500個sin需要時間0.047。
1萬個sin,4 core,最佳時間顯然也在此附近。
你總歸要算1萬個sin。分到四個核心。除此而外,別的優化都是扯。
因為sin極其昂貴。其他的乘法加法相比之下什麼也不是。
(所以我非常不理解他那個mpi為何好那麼多。
我機器上mpi版本亂了,rank總是不變。沒法測。)

【在 B********s 的大作中提到】
: 在俺这儿也是比老代码慢
: 这个新代码就是用了double buffer手动reduce,俺是看不出来有啥优势。
: 还是楼主改了编译选项?
: PS, 你的机器是4核,所以np=4最快也是预料之中

c*******v
发帖数: 2599
133
我覺得沒差別的。
1萬次sin dominate了所有的東西。相比於這一萬次sin之計算。
其他的東西略等於無。所以計算量就在於如何分配這1萬次sin到不同的core。
沒有別的任務時,平均分配為最佳。
我試過了改一點程序,變成只需要計算五千次sin。
仍然是1萬個loop。結果基本上就是減40%的時間。

mpi

【在 l*******s 的大作中提到】
: 每次reduce由原来的2次sync变成1次。
: 原来在omp for reduction 结束是要sync一次(implicit barrier)
: 在omp single 结束是要sync一次(implicit barrier)
: 有人建议用omp master, 结束后加一个barrier, 效果基本是一样的。
: 新的code,只在所有thread 给shared数组darr赋值后有一个barrier,
: 其他都用重复计算代替barrier。
: 这样没有omp master 或 omp single.
: 所有线程create以后就不休息,一直active。
: 我的compiling flags是这样的
: icc -O3 -qopenmp -march=native -ffast-math reduction_mpi.c -o reduction_mpi

j**f
发帖数: 28
134
用轮换数组来换一个barrier的主意不错. 不过也说明np大了以后,求和比求dot
product 还慢.
不过我还是很不喜欢加法那一部分,要是np=1024,4096怎么办?但是要合作求和,必须加
法都同步,好像不现实;感觉起码需要硬件支持.
不知道GPU是怎么处理的?有没有可能block内步合作一下,然后共享.

【在 l*******s 的大作中提到】
: 多谢各位回复。 我找到目前最佳reduce了。
: OMP performance:
: np = 1 sum = 6992.953984, loop time = 0.246376 sec, total time = 0.250978
: np = 2 sum = 6992.953984, loop time = 0.160334 sec, total time = 0.164939
: np = 4 sum = 6992.953984, loop time = 0.105096 sec, total time = 0.110154
: np = 8 sum = 6992.953984, loop time = 0.074775 sec, total time = 0.080252
: np = 16 sum = 6992.953984, loop time = 0.049352 sec, total time = 0.057083
: np = 32 sum = 6992.953984, loop time = 0.101747 sec, total time = 0.109425
: 我的最佳redcution 实施
: #include

g****t
发帖数: 31659
135
你们试过omp simd吗?
我用其换掉reduction。没什么大区别。
还是np=4最快。0.05几秒。


: 用轮换数组来换一个barrier的主意不错. 不过也说明np大了以后,求和比求dot

: product 还慢.

: 不过我还是很不喜欢加法那一部分,要是np=1024,4096怎么办?但是要合作求和,
必须加

: 法都同步,好像不现实;感觉起码需要硬件支持.

: 不知道GPU是怎么处理的?有没有可能block内步合作一下,然后共享.



【在 j**f 的大作中提到】
: 用轮换数组来换一个barrier的主意不错. 不过也说明np大了以后,求和比求dot
: product 还慢.
: 不过我还是很不喜欢加法那一部分,要是np=1024,4096怎么办?但是要合作求和,必须加
: 法都同步,好像不现实;感觉起码需要硬件支持.
: 不知道GPU是怎么处理的?有没有可能block内步合作一下,然后共享.

l*******s
发帖数: 7316
136
我正在写一个log(np)的code, 完全不需要barrier, 也不要隐式barrier.
希望能有更好的performance.

250978
164939
110154
080252
057083
109425

【在 j**f 的大作中提到】
: 用轮换数组来换一个barrier的主意不错. 不过也说明np大了以后,求和比求dot
: product 还慢.
: 不过我还是很不喜欢加法那一部分,要是np=1024,4096怎么办?但是要合作求和,必须加
: 法都同步,好像不现实;感觉起码需要硬件支持.
: 不知道GPU是怎么处理的?有没有可能block内步合作一下,然后共享.

b***i
发帖数: 3043
137
2005年左右我做了一个矩阵乘法的项目,大概是最多十多万列乘几千行的矩阵自乘 T *
T',得到方阵。大概要算几十分钟到几个小时。我用了多线程。在TACC上96个芯片大概
加速48倍以上。其中就用了循环内部手动展开8个乘法的方法可以超标量吧。也遇到过
O3结果不对的问题。
你这个循环最后不到一秒结束,看不出哪里是瓶颈。但是到我那个数量级,又有cache
大小的限制了。

【在 l*******s 的大作中提到】
: 没找到更合适的版面讨论这个问题,就在这里问吧.
: 我发现OpenMP的reduction效率很差,做同样的两个向量的内积,MPI要比OpenMP还快。
: MPI是分布内存,需要信息交换才能完成reduction。 结果比使用共享内存的OpenMP还
: 快。
: 这说明OpenMP的reduction没有搞好。我不知道是我使用的系统的问题还是普遍问题。
: 有人有类似的经验吗? 怎么解决?
: 我提供了一个code,然后再大家的反馈后做了修改。 现在把code也帖再这里。
: 省得大家爬楼。
: 现在的code 还是模仿dot product, 只不过 element都是compute on the fly.
: 所以code中没有大的数组,减少cache missing。

g****t
发帖数: 31659
138
“循环内部手动展开8个乘法”
這個可否展開說說?

*
cache

【在 b***i 的大作中提到】
: 2005年左右我做了一个矩阵乘法的项目,大概是最多十多万列乘几千行的矩阵自乘 T *
: T',得到方阵。大概要算几十分钟到几个小时。我用了多线程。在TACC上96个芯片大概
: 加速48倍以上。其中就用了循环内部手动展开8个乘法的方法可以超标量吧。也遇到过
: O3结果不对的问题。
: 你这个循环最后不到一秒结束,看不出哪里是瓶颈。但是到我那个数量级,又有cache
: 大小的限制了。

b***i
发帖数: 3043
139
就是循环内部进行8个乘法,而不是1个,那么循环变量要每次加8。这样做,循环次数
可以减少,那么循环变量增加且比较那个指令相对于加法就少了。这个技巧前面几个帖
子说过了。

【在 g****t 的大作中提到】
: “循环内部手动展开8个乘法”
: 這個可否展開說說?
:
: *
: cache

b***i
发帖数: 3043
140
就是循环内部进行8个乘法,而不是1个,那么循环变量要每次加8。这样做,循环次数
可以减少,那么循环变量增加且比较那个指令相对于加法就少了。这个技巧前面几个帖
子说过了。

【在 g****t 的大作中提到】
: “循环内部手动展开8个乘法”
: 這個可否展開說說?
:
: *
: cache

c*******v
发帖数: 2599
141
哦。循環變量一次加8這個辦法我也試了。
確實有一致的提高。

【在 b***i 的大作中提到】
: 就是循环内部进行8个乘法,而不是1个,那么循环变量要每次加8。这样做,循环次数
: 可以减少,那么循环变量增加且比较那个指令相对于加法就少了。这个技巧前面几个帖
: 子说过了。

l*******s
发帖数: 7316
142
已经实施了这个tree-base reduce,结果稍好一点,但还是不理想。
写code并调试,搞了一整天。
np = 1 nt = 1 sum = 6992.953984, loop time = 0.246602 sec, total time = 0.
261854
np = 1 nt = 2 sum = 6992.953984, loop time = 0.150202 sec, total time = 0.
165216
np = 1 nt = 4 sum = 6992.953984, loop time = 0.101883 sec, total time = 0.
116406
np = 1 nt = 8 sum = 6992.953984, loop time = 0.070848 sec, total time = 0.
085032
np = 1 nt = 16 sum = 6992.953984, loop time = 0.053922 sec, total time = 0.
070401
np = 1 nt = 32 sum = 6992.953984, loop time = 0.048791 sec, total time = 0.
104547

【在 l*******s 的大作中提到】
: 我正在写一个log(np)的code, 完全不需要barrier, 也不要隐式barrier.
: 希望能有更好的performance.
:
: 250978
: 164939
: 110154
: 080252
: 057083
: 109425

g****t
发帖数: 31659
143
我覺得你的機器理論最快速度=單線程時間/核心數×調度損耗係數。
核心越多,調度損耗係數越大。我猜用別的問題可以測量出來調度損耗係數。
0.24是單線程之結果。我的4核心laptop此係數為4/3.2。
問題規模大,則越接近:
單線程時間/核心數×調度損耗係數

【在 l*******s 的大作中提到】
: 已经实施了这个tree-base reduce,结果稍好一点,但还是不理想。
: 写code并调试,搞了一整天。
: np = 1 nt = 1 sum = 6992.953984, loop time = 0.246602 sec, total time = 0.
: 261854
: np = 1 nt = 2 sum = 6992.953984, loop time = 0.150202 sec, total time = 0.
: 165216
: np = 1 nt = 4 sum = 6992.953984, loop time = 0.101883 sec, total time = 0.
: 116406
: np = 1 nt = 8 sum = 6992.953984, loop time = 0.070848 sec, total time = 0.
: 085032

g****t
发帖数: 31659
144
timeX = 24748,sum = 4663.721598, time = 0.024740 sec, np = 1
timeX = 17010,sum = 4663.721598, time = 0.016904 sec, np = 2
timeX = 14825,sum = 4663.721598, time = 0.013061 sec, np = 4
timeX = 206982,sum = 4663.721598, time = 0.205362 sec, np = 8
timeX = 658506,sum = 4663.721598, time = 0.656862 sec, np = 16
timeX = 2003551,sum = 4663.721598, time = 2.003309 sec, np = 32
timeX = 5061292,sum = 4663.721598, time = 5.060614 sec, np = 64
另外你看下n=1000,而不是一萬時,我機器的結果。比率只有1.8.
明顯4核心之提高遠小於n=10000的情況。
多線程最好的情況,其比數遠遠不到3.11。(此為n=1萬的比數。)

【在 g****t 的大作中提到】
: 我覺得你的機器理論最快速度=單線程時間/核心數×調度損耗係數。
: 核心越多,調度損耗係數越大。我猜用別的問題可以測量出來調度損耗係數。
: 0.24是單線程之結果。我的4核心laptop此係數為4/3.2。
: 問題規模大,則越接近:
: 單線程時間/核心數×調度損耗係數

g****t
发帖数: 31659
145
n=100,R=1.14。多核對小任務幾乎沒有提高。
n=10萬時,比數為3.51
n=百萬,比數為3.52
以100,1000,1萬,十萬,百萬的比數而言。規律似乎是明顯的。

【在 g****t 的大作中提到】
: timeX = 24748,sum = 4663.721598, time = 0.024740 sec, np = 1
: timeX = 17010,sum = 4663.721598, time = 0.016904 sec, np = 2
: timeX = 14825,sum = 4663.721598, time = 0.013061 sec, np = 4
: timeX = 206982,sum = 4663.721598, time = 0.205362 sec, np = 8
: timeX = 658506,sum = 4663.721598, time = 0.656862 sec, np = 16
: timeX = 2003551,sum = 4663.721598, time = 2.003309 sec, np = 32
: timeX = 5061292,sum = 4663.721598, time = 5.060614 sec, np = 64
: 另外你看下n=1000,而不是一萬時,我機器的結果。比率只有1.8.
: 明顯4核心之提高遠小於n=10000的情況。
: 多線程最好的情況,其比數遠遠不到3.11。(此為n=1萬的比數。)

1 (共1页)
进入Programming版参与讨论