在针对顺序运行进行优化的程序上使用 openMP 后没有性能提升

2023-12-09

我已经尽可能地优化了顺序运行的功能。 当我使用 openMP 时,我发现性能没有提高。 我在1核机器和8核机器上测试了我的程序,性能是一样的。
将年份设置为 20,我有
1 核:1 秒。
8 核:1 秒。

将年份设置为 25 我有
1 核:40 秒。
8 核:40 秒。

1核机器:我的笔记本电脑的intel core 2 duo 1.8 GHz,ubuntu linux
8核机器:3.25 GHz,ubuntu linux

我的程序枚举二项式树的所有可能路径,并对每个路径做一些工作。因此,我的循环大小呈指数级增长,并且我希望 openMP 线程的占用空间为零。在我的循环中,我只减少一个变量。所有其他变量都是只读的。我只使用我编写的函数,并且我认为它们是线程安全的。

我还在我的程序上运行 Valgrind cachegrind。我不完全理解输出,但似乎没有缓存未命中或错误共享。

我编译用

gcc -O3 -g3 -Wall -c -fmessage-length=0 -lm -fopenmp -ffast-math

我的完整程序如下。抱歉发布了很多代码。我对 openMP 和 C 都不熟悉,而且我无法在不失去主要任务的情况下继续我的代码。

使用 openMP 时如何提高性能?
它们是一些编译器标志还是 C 技巧,可以使程序运行得更快?

test.c

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
#include "test.h"

int main(){

    printf("starting\n");
    int year=20;
    int tradingdate0=1;

    globalinit(year,tradingdate0);

    int i;
    float v=0;
    long n=pow(tradingdate0+1,year);
    #pragma omp parallel for reduction(+:v)
    for(i=0;i<n;i++)
        v+=pathvalue(i);

    globaldel();
    printf("finished\n");
    return 0;
}

//***function on which openMP is applied
float pathvalue(long pathindex) {
    float value = -ctx.firstpremium;
    float personalaccount = ctx.personalaccountat0;
    float account = ctx.firstpremium;
    int i;
    for (i = 0; i < ctx.year-1; i++) {
        value *= ctx.accumulationfactor;
        double index = getindex(i,pathindex);
        account = account * index;
        double death = fmaxf(account,ctx.guarantee[i]);
        value += qx(i) * death;
        if (haswithdraw(i)){
            double withdraw = personalaccount*ctx.allowed;
            value += px(i) * withdraw;
            personalaccount = fmaxf(personalaccount-withdraw,0);
            account = fmaxf(account-withdraw,0);
        }
    }

    //last year
    double index = getindex(ctx.year-1,pathindex);
    account = account * index;
    value+=fmaxf(account,ctx.guarantee[ctx.year-1]);

    return value * ctx.discountfactor;
}



int haswithdraw(int period){
    return 1;
}

float getindex(int period, long pathindex){
    int ndx = (pathindex/ctx.chunksize[period])%ctx.tradingdate;
    return ctx.stock[ndx];
}

float qx(int period){
    return 0;
}

float px(int period){
    return 1;
}

//****global
struct context ctx;

void globalinit(int year, int tradingdate0){
    ctx.year = year;
    ctx.tradingdate0 = tradingdate0;
    ctx.firstpremium = 1;
    ctx.riskfreerate = 0.06;
    ctx.volatility=0.25;
    ctx.personalaccountat0 = 1;
    ctx.allowed = 0.07;
    ctx.guaranteerate = 0.03;
    ctx.alpha=1;
    ctx.beta = 1;
    ctx.tradingdate=tradingdate0+1;
    ctx.discountfactor = exp(-ctx.riskfreerate * ctx.year);
    ctx.accumulationfactor = exp(ctx.riskfreerate);
    ctx.guaranteefactor = 1+ctx.guaranteerate;
    ctx.upmove=exp(ctx.volatility/sqrt(ctx.tradingdate0));
    ctx.downmove=1/ctx.upmove;

    ctx.stock=(float*)malloc(sizeof(float)*ctx.tradingdate);
    int i;
    for(i=0;i<ctx.tradingdate;i++)
        ctx.stock[i]=pow(ctx.upmove,ctx.tradingdate0-i)*pow(ctx.downmove,i);

    ctx.chunksize=(long*)malloc(sizeof(long)*ctx.year);
    for(i=0;i<year;i++)
        ctx.chunksize[i]=pow(ctx.tradingdate,ctx.year-i-1);

    ctx.guarantee=(float*)malloc(sizeof(float)*ctx.year);
    for(i=0;i<ctx.year;i++)
        ctx.guarantee[i]=ctx.beta*pow(ctx.guaranteefactor,i+1);
}

void globaldel(){
    free(ctx.stock);
    free(ctx.chunksize);
    free(ctx.guarantee);
}

test.h

float pathvalue(long pathindex);
int haswithdraw(int period);
float getindex(int period, long pathindex);
float qx(int period);
float px(int period);
//***global
struct context{
    int year;
    int tradingdate0;
    float firstpremium;
    float riskfreerate;
    float volatility;
    float personalaccountat0;
    float allowed;
    float guaranteerate;
    float alpha;
    float beta;
    int tradingdate;
    float discountfactor;
    float accumulationfactor;
    float guaranteefactor;
    float upmove;
    float downmove;
    float* stock;
    long* chunksize;
    float* guarantee;
};
struct context ctx;
void globalinit();
void globaldel();

EDIT我将所有全局变量简化为常量。 20 年来,该程序的运行速度提高了一倍(太棒了!)。我尝试设置线程数OMP_NUM_THREADS=4 ./test例如。但它并没有给我带来任何性能提升。
我的 gcc 有问题吗?

test.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <omp.h>
#include "test.h"


int main(){

    starttimer();
    printf("starting\n");
    int i;
    float v=0;

    #pragma omp parallel for reduction(+:v)
    for(i=0;i<numberofpath;i++)
        v+=pathvalue(i);

    printf("v:%f\nfinished\n",v);
    endtimer();
    return 0;
}

//function on which openMP is applied
float pathvalue(long pathindex) {
    float value = -firstpremium;
    float personalaccount = personalaccountat0;
    float account = firstpremium;
    int i;
    for (i = 0; i < year-1; i++) {
        value *= accumulationfactor;
        double index = getindex(i,pathindex);
        account = account * index;
        double death = fmaxf(account,guarantee[i]);
        value += death;
        double withdraw = personalaccount*allowed;
        value += withdraw;
        personalaccount = fmaxf(personalaccount-withdraw,0);
        account = fmaxf(account-withdraw,0);
    }

    //last year
    double index = getindex(year-1,pathindex);
    account = account * index;
    value+=fmaxf(account,guarantee[year-1]);

    return value * discountfactor;
}



float getindex(int period, long pathindex){
    int ndx = (pathindex/chunksize[period])%tradingdate;
    return stock[ndx];
}

//timing
clock_t begin;

void starttimer(){
    begin = clock();
}

void endtimer(){
    clock_t end = clock();
    double elapsed = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("\nelapsed: %f\n",elapsed);
}

test.h

float pathvalue(long pathindex);
int haswithdraw(int period);
float getindex(int period, long pathindex);
float qx(int period);
float px(int period);
//timing
void starttimer();
void endtimer();
//***constant
const int year= 20 ;
const int tradingdate0= 1 ;
const float firstpremium= 1 ;
const float riskfreerate= 0.06 ;
const float volatility= 0.25 ;
const float personalaccountat0= 1 ;
const float allowed= 0.07 ;
const float guaranteerate= 0.03 ;
const float alpha= 1 ;
const float beta= 1 ;
const int tradingdate= 2 ;
const int numberofpath= 1048576 ;
const float discountfactor= 0.301194211912 ;
const float accumulationfactor= 1.06183654655 ;
const float guaranteefactor= 1.03 ;
const float upmove= 1.28402541669 ;
const float downmove= 0.778800783071 ;
const float stock[2]={1.2840254166877414, 0.7788007830714049};
const long chunksize[20]={524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1};
const float guarantee[20]={1.03, 1.0609, 1.092727, 1.1255088100000001, 1.1592740743, 1.1940522965290001, 1.2298738654248702, 1.2667700813876164, 1.304773183829245, 1.3439163793441222, 1.384233870724446, 1.4257608868461793, 1.4685337134515648, 1.512589724855112, 1.557967416600765, 1.6047064390987882, 1.6528476322717518, 1.7024330612399046, 1.7535060530771016, 1.8061112346694148};

即使您的程序受益于使用 OpenMP,您也不会看到它,因为您测量了错误的时间。

clock()返回总CPU时间花费在所有线程。如果您使用四个线程运行并且每个线程运行 1/4 的时间,clock()由于 4*(1/4) = 1,仍然会返回相同的值。您应该测量挂钟时间反而。

将呼叫替换为clock() with omp_get_wtime() or gettimeofday()。它们都提供高精度的挂钟计时。

附:为什么周围有这么多人使用SOclock()为了计时?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在针对顺序运行进行优化的程序上使用 openMP 后没有性能提升 的相关文章

  • 如何在 VC++ CString 中验证有效的整数和浮点数

    有人可以告诉我一种有效的方法来验证 CString 对象中存在的数字是有效整数还是浮点数吗 Use tcstol http msdn microsoft com en us library w4z2wdyc aspx and tcstod
  • 使用 CMake 时如何导出 Emscripten 中的 C 函数

    In 本教程 https emscripten org docs porting connecting cpp and javascript Interacting with code html interacting with code
  • 循环遍历 C 结构中的元素以提取单个元素的值和数据类型

    我有一个要求 我有一个 C 语言的大结构 由大约 30 多个不同数据类型的不同元素组成 typedef struct type1 element1 type2 element2 type3 element3 type2 element4 1
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 什么是空终止字符串?

    它与什么不同标准 字符串 http www cplusplus com reference string string 字符串 实际上只是一个数组chars 空终止字符串是指其中包含空字符的字符串 0 标记字符串的结尾 不一定是数组的结尾
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 在 .NET MAUI 中实现 TouchTracking

    我一直致力于将我们的应用程序从 Xamarin Forms 迁移到 NET MAUI 我们的应用程序几乎没有绘图功能 用户可以用手指进行绘图 我们用了TouchTrackingXamarin Forms 中的 nuget 包 但与 NET
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 将 Lambda 表达式树与 IEnumerable 结合使用

    我一直在尝试了解有关使用 Lamba 表达式树的更多信息 因此我创建了一个简单的示例 这是代码 如果作为 C 程序粘贴到 LINQPad 中 它可以工作 void Main IEnumerable
  • 代码中的.net Access Forms身份验证“超时”值

    我正在向我的应用程序添加注销过期警报 并希望从我的代码访问我的 web config 表单身份验证 超时 值 我有什么办法可以做到这一点吗 我认为您可以从 FormsAuthentication 静态类方法中读取它 这比直接读取 web c
  • 在 Win32 控制台应用程序中设置光标位置

    如何在 Win32 控制台应用程序中设置光标位置 最好 我想避免制作句柄并使用 Windows 控制台功能 我花了整个早上沿着那条黑暗的小巷跑 它产生的问题比它解决的问题还要多 我似乎记得当我在大学时使用 stdio 做这件事相对简单 但我
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我
  • 在 System.Type 上使用条件断点时出错

    这是函数 public void Init System Type Type this Type Type BuildFieldAttributes BuildDataColumns FieldAttributes 我在第一行设置了一个断点
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names

随机推荐

  • Oracle 10g 按日期选择查询没有返回结果

    我有一些令人困惑的问题 SQL gt select login status date modified from users where login zack 661 and date modified 05 MAR 14 no rows
  • Javascript stringify '%%' 丢失百分号

    为什么 stringify 的输出缺少百分号 var a dp var t JSON stringify a console log t t 结果是 t dp 为什么没有结果 t dp Thanks 正如文档中所指定的console log
  • 导入错误:“没有名为模块”*确实*存在[重复]

    这个问题在这里已经有答案了 当我启动金字塔保存时 我得到这个堆栈跟踪 python which pserve etc development ini Traceback most recent call last File home hug
  • 如何从 api 获取整个 Facebook 好友列表

    有没有办法使用 api 获取整个 Facebook 好友列表 我尝试了很多事情 这是我的镜头 FacebookClient f new FacebookClient access token f IsSecureConnection tru
  • 使用扩展方法表示的嵌套“from”LINQ 查询

    如何使用扩展方法语法编写此 LINQ 查询 var query from a in sequenceA from b in sequenceB select 为了供您将来参考 此表格的所有问题均由 C 规范第 7 16 节解答 本段回答了您
  • IntelliJ IDEA 终端特殊字符

    我最近开始在 Windows 10 上使用 IntelliJ IDEA Ultimate 并且非常想使用集成终端 但是 我无法让它与特殊字符 例如德语元音变音或 等 一起使用 如果我没有一些以 开头的文件夹 我无法重命名这些文件夹 那不会是
  • 移除边框后,边距超出 div 范围

    源于我网站上边框和边距的实际问题 我制作了这个测试示例 我认为它有点奇怪
  • 如何在Java中拥有多重地图功能?

    我想要具有以下功能MultiMap在 Java 中 提供与 cpp MultiMap 相同的功能 以便我能够拥有多个具有相同值的键 容器中的多个元素可以具有相同的键 我认为这会起作用 TreeMap
  • 从列表值动态创建匿名对象c#

    我有一个字符串列表 或者可以是数组 我想从中动态创建匿名对象 我该怎么做呢 var dataSet new DataSet dataSet ReadXml var dataTable dataSet Tables 0 var dataRow
  • Javascript 可以检测嵌入的 Youtube 视频何时结束吗?

    我有一个包含视频的 div div 的背景有一个假的 播放 按钮 我将其设计为用作播放按钮 而不是 Youtube 的标准视频 播放 按钮 视频最初设置为 display none 我部署了下面的代码 以便当您单击 div 时 div 消失
  • 蒙特卡洛圆周率计算可以用来创造世界纪录吗?

    我有这个随机函数来计算 pi蒙特卡罗风格 max 10000000 format long in 0 tic for k 1 max x rand y rand if sqrt x 2 y 2 lt 1 in in 1 end end to
  • 以编程方式更改 Windows 电源设置

    是否可以更改笔记本电脑合上盖子时的省电行为休眠 待机 关机 to 没做什么来自 NET 框架 Edit 看来 通过将值设置为 待机 并阻止我的应用程序的待机 可以检测到盖子关闭事件 这正是我真正想要的 I found 这个问题它涉及检测盖子
  • 重新启动自己 - 我可以从头开始重新初始化一切吗?

    我有这样的事情 public static final String path static path loadProperties config conf getProperty path public static void main
  • AnyLogic Attractor 奇怪的行为

    我的理解是 节点内的吸引子的容量应该为 1 从某种意义上说 在 3D 动画中 每个吸引子应该只有一个代理 当我运行模型时 我看到同一个吸引子上有两个代理形状 而其他吸引子是空的 这是正常行为吗 有没有办法防止这种情况发生 请注意 这种情况并
  • pgAdmin III 的错误行为?

    我在 pgAdmin 上进行查询时偶然发现了这种奇怪的行为 我已连接到运行 PostgreSQL 9 1 9 的服务器 我有一个名为 messages 的表 其定义如下 ghareh godot psql psql 9 1 9 Type h
  • 错误:“f”的类型与之前的“f”声明存在冲突

    这段代码只是我在实际代码中发现的一种情况 它非常大 所以我给出这个 在此代码中 结构 struct node 未定义 它是在另一个 c 源文件中定义的 我的c源代码 test c 1 include
  • 字节变量的 VBA 溢出错误

    有人可以解释一下为什么当操作的接收者时以下代码会在 VBA 中生成溢出错误c is an Integer Dim a As byte b As Byte Dim c As Integer a 3 b 100 c a b 或者这是否意味着涉及
  • 将整数转换为十六进制

    我只需要将整数转换为十六进制 实际上我有一个字符数组 在其中存储十六进制值 int var var self getValue char hexValues 5 hexValues 0 0x02 hexValues 1 0x04 hexVa
  • Heroku 应用程序和 mysql 的 config.php 代码出错

    我正在使用 Heroku for PHP 我查看了 Heroku 日志 发现 config php 代码中有错误 我正在为我的编码组合制作一个 Spotify 克隆 我使用 xampp apache mysql 成功制作了该组合 但现在我需
  • 在针对顺序运行进行优化的程序上使用 openMP 后没有性能提升

    我已经尽可能地优化了顺序运行的功能 当我使用 openMP 时 我发现性能没有提高 我在1核机器和8核机器上测试了我的程序 性能是一样的 将年份设置为 20 我有1 核 1 秒 8 核 1 秒 将年份设置为 25 我有1 核 40 秒 8