多线程基准测试

2023-12-25

我进行了大量的数学计算来计算孪生素数 https://en.wikipedia.org/wiki/Twin_prime范围内的数字,我已在线程之间划分任务。

在这里您可以看到执行时间与线程数的关系。

我的问题是关于以下理由的:

  1. 为什么单线程和双线程的性能非常相似?

  2. 为什么使用 5 或 7 线程时执行时间会下降,而使用 6 或 8 线程时执行时间会增加? (我在几次测试中都经历过这一点。)

  3. 我用过8核的电脑。我可以声称 2×n (where n是核心数)根据经验,线程数是一个很好的数量吗?

  4. 如果我使用 RAM 使用率高的代码,我是否会期望配置文件中出现类似的趋势,或者它会随着线程数量的增加而发生巨大变化吗?

这是代码的主要部分,只是为了表明它没有使用太多 RAM。

bool is_prime(long a)
{
    if(a<2l)
        return false;
    if(a==2l)
        return true;
    for(long i=2;i*i<=a;i++)
        if(a%i==0)
            return false;
    return true;
}

uint twin_range(long l1,long l2,int processDiv)
{
    uint count=0;
    for(long l=l1;l<=l2;l+=long(processDiv))
        if(is_prime(l) && is_prime(l+2))
        {
            count++;
        }
    return count;
}

规格:

$ lsb_release -a

Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:    16.04
Codename:   xenial

$ lscpu

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 94
Model name:            Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
Stepping:              3
CPU MHz:               799.929
CPU max MHz:           4000.0000
CPU min MHz:           800.0000
BogoMIPS:              6815.87
Virtualisation:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7
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 art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp

更新(接受答案后)

新的配置文件:

改进后的代码如下。现在,工作量分配得相当公平。

bool is_prime(long a)
{
    if(a<2l)
        return false;
    if(a==2l)
        return true;
    for(long i=2;i*i<=a;i++)
        if(a%i==0)
            return false;
    return true;
}


void twin_range(long n_start,long n_stop,int index,int processDiv)
{
    // l1+(0,1,...,999)+0*1000
    // l1+(0,1,...,999)+1*1000
    // l1+(0,1,...,999)+2*1000
    // ...

    count=0;
    const long chunks=1000;
    long r_begin=0,k=0;
    for(long i=0;r_begin<=n_stop;i++)
    {
        r_begin=n_start+(i*processDiv+index)*chunks;
        for(k=r_begin;(k<r_begin+chunks) && (k<=n_stop);k++)
        {
            if(is_prime(k) && is_prime(k+2))
            {
                count++;
            }
        }
    }

    std::cout
        <<"Thread "<<index<<" finished."
        <<std::endl<<std::flush;
    return count;
}

考虑一下您的程序将在以下时间完成:last线程已完成对其数字范围的检查。也许某些线程比其他线程更快?

需要多久is_prime()怎样判断偶数是素数?它将在第一次迭代时找到它。查找奇数的素数将至少需要两次迭代,如果 a 是素数,则可能需要最多 sqrt(a) 次迭代。is_prime()当给它一个大素数时,它会比给一个偶数慢得多!

在两个线程的情况下,一个线程将检查 100000000、100000002、100000004 等的素数,而另一个线程将检查 100000001、100000003、100000005 等。一个线程检查所有偶数,而另一个线程检查所有奇数(包括所有那些慢素数!)。

把你的线索打印出来("Thread at %ld done", l1)当它们完成时,我认为您会发现某些线程比其他线程快得多,这是由于您在线程之间划分域的方式所致。偶数线程会将所有偶数值赋予同一线程,导致分区特别差,这就是偶数线程数比奇数线程慢的原因。

这将成为一部很棒的XKCD风格的漫画。 “我们需要检查所有这些数字来找到素数!用手!” “好吧,我会检查evens,你会赔率。”

这里真正的问题是,像您所做的那样的固定域分解要求每个分区花费相同的时间才能达到最佳状态。

解决这个问题的方法是动态进行分区。常用的模式涉及以块的形式请求工作的工作线程池。如果该块与线程将完成的总工作相比较小,则所有线程将在相似的时间内完成其工作。

对于您的问题,您可能有一个互斥锁保护的全局数据集start_number, stop_number, total_twins。每个线程都会保存start_number在将其全局值增加之前chunk_size。然后它搜索范围[saved_start_number, saved_start_number+chunk_size),将发现的双胞胎数量添加到全球total_twins完成后。工作线程继续执行此操作,直到start_number >= stop_number。对全局变量的访问使用互斥体进行保护。人们必须调整块大小,以限制因获取块的成本和互斥体争用而导致的低效率,以及由于空闲工作线程没有更多块可分配而另一个线程仍在处理其最后一个块而导致的低效率。如果您使用原子增量来请求块,则块大小可能会小到单个值,但如果在分布式计算系统中需要网络请求,则块大小将需要大得多。这就是它如何工作的概述。

顺便说一句,你的is_prime()测试很幼稚而且非常慢。如果一个数不能被2整除,它能被4整除吗?一个人可以做得更好!

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

多线程基准测试 的相关文章

  • “benaphores”值得在现代操作系统上实施吗?

    当我还是一名 BeOS 程序员时 我读过本文 http www haiku os org legacy docs benewsletter Issue1 26 html Engineering1 26作者 Benoit Schillings
  • 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 更快?

    使用 ConcurrentHashMap 我发现computeIfAbsent 比putIfAbsent 慢两倍 这是简单的测试 import java util ArrayList import java util List import
  • iPhone SDK - 在后台线程中运行重复进程

    我有一个iPhone我想在其中每隔一段时间在后台执行一个方法的应用程序1第二 所以在我的主线程中 我有以下代码UIViewController viewDidLoad NSTimer timerWithTimeInterval 1 0 ta
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • WPF 从主线程以外的其他线程截屏

    我有一个线程用于侦听 WPF 应用程序的命令 如果 WPF 应用程序收到截取屏幕截图的命令 则任务将移交给 screenshotService 我在互联网上的某个地方找到了一些代码来截取屏幕截图 似乎可以工作 但我还没有想清楚 我无法从另一
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 集中回滚-用于使用@transactional

    是否可以告诉Spring回滚异常MyException也RuntimeException使用时在 XML 配置中 transactional 我知道可以在注释中设置回滚 但如果我有很多服务都设置相同的异常 那么这似乎是多余的 我看到人们建议
  • JUnit 5:指定嵌套测试的执行顺序

    是否可以以固定的执行顺序在其他一些测试之间执行多个嵌套测试 E g TestInstance Lifecycle PER CLASS TestMethodOrder OrderAnnotation class class MyTest pr
  • POSIXct 日期转换错误[重复]

    这个问题在这里已经有答案了 将一组字符格式的日期转换为 POSIXct 对象时 我遇到了以下错误 示例数据 t lt c 3 11 2007 1 30 3 11 2007 2 00 4 11 2007 2 00 str t chr 1 3
  • 如何使用区域设置获取特定国家/地区的货币符号?

    我已经尝试过这段代码 它给了我Country Code对于某些国家而不是currency symbol 我想要货币符号而不是代码 数组 resourcesList 包含所有具有其代码的国家 地区 String m String Array
  • 如何在 Android 应用程序中指定和添加自定义打印机?

    我正在为 Android 创建一个应用程序 所需的应用程序功能的一部分是用户可以选择一个特殊的打印机 我们将其称为传输打印机 它将将要打印的文档传递到在外部服务器上运行的进程 我需要采取哪些步骤才能将自定义打印机添加到 Android 打印
  • 双包含解决方案?

    在 C 中 我遇到了双重包含的问题 文件 stuffcollection h pragma once ifndef STUFFCOLLECTION H define STUFFCOLLECTION H include Stage h cla
  • Tensorflow、try 和 except 不处理异常

    我是张量流的新手 我在这里遇到了一个恼人的问题 我正在制作一个程序 加载使用以下命令拍摄的图像 原始数据 tf WholeFileReader read image name queue 从 tfrecord 文件中读取 然后使用tf im
  • 在同一表达式中调用具有局部副作用的函数两次是否是未定义的行为?

    int f static int i 0 return i int g return f f Does g return 3或者是结果undefined 章节和诗句 http www open std org jtc1 sc22 wg14
  • 属性 insetForeground 已经定义

    更新到新版本后 com android support design 22 2 0 我收到这个错误 属性 insetForeground 已经定义 请记住 我正在使用 romannurikScrimInsetsFrameLayout jav
  • Ruby on Rails,找不到有效的 gem 'rails'

    我安装了 ruby 并更新了 ruby gems 现在我想下载 Rails 3 2 13 我写 gem install Rails v 3 2 13 我需要这个版本 我有这个错误 ERROR Could not find a valid g
  • 为什么我们需要在Python中进行编码和解码?

    编码 解码的用例是什么 我的理解是 编码用于将字符串转换为字节字符串 以便能够在程序中传递非 ascii 数据 而decode就是将这个字节串转换回字符串 有点遵循 示例显示即使未编码 解码 非 ascii 字符也能成功打印 例子 val1
  • 在 PDF 中插入换行符

    我正在使用 PHP 即时生成一些 PDF 文件 我的问题是我需要在将插入 PDF 文件的文本的某些部分插入换行符 就像是 pdf gt InsertText Line one n nLine two 所以它打印 Line one Line
  • Visual Studio 2015 非常慢

    我刚安装完 整个IDE速度超级慢 看起来它正在后台进行某种繁重的 CPU 调用 整个 IDE 几乎冻结并在大约 2 3 秒内变得无响应 我在使用 Visual Studio 2013 Ultimate 时没有遇到此问题 我正在运行 Visu
  • 添加变量导致的段错误

    诚然 我是一个纯 C 新手 但这让我难住了 我正在研究链表实现以进行练习 并且通过简单地将变量添加到 split node 函数中 我遇到了段错误 include
  • 比较两个表的值并列出不同的行

    这个问题与这个问题 https stackoverflow com questions 4602083 sql compare data from two tables 4604221 comment 7562192 但只是略有不同 我有
  • 如何像 jQuery 那样实现链接模式? [复制]

    这个问题在这里已经有答案了 如何创建一个像 jQuery 使用的前缀 例如 在 jQuery 中我可以使用 footer css display none 我想启用类似的语法 如下所示 google footer chrome displa
  • Java Robot createScreenCapture 性能

    我需要抓取一系列屏幕截图并将它们连接成一部电影 我正在尝试使用 java Robot 类来捕获屏幕 但 createScreenCapture 方法在我的机器上花费了超过 1 秒的时间 我什至连 1 fps 都达不到 有办法加快速度吗 或者
  • 如何覆盖android home按钮

    我一直在搜索 Android 文档和 stackoverflow 我正在阅读的大多数答案都说您无法禁用或覆盖 Android 主页按钮 尝试过 不起作用 https stackoverflow com questions 6507063 h
  • Common LISP:将(未知)struct 对象转换为 plist?

    defstruct mydate constructor make mydate year month day year 1970 month 1 day 1 defvar date1 make mydate 1992 1 1 问题更普遍
  • 多线程基准测试

    我进行了大量的数学计算来计算孪生素数 https en wikipedia org wiki Twin prime范围内的数字 我已在线程之间划分任务 在这里您可以看到执行时间与线程数的关系 我的问题是关于以下理由的 为什么单线程和双线程的