当我调用函数时,执行时间是 6.8 秒。 从线程调用它的时间是 3.4 秒 当使用 2 线程时 1.8 秒。无论我使用什么优化,口粮都保持不变。
在 Visual Studio 中,时间与预期的一样,分别为 3.1、3 和 1.7 秒。
#include<math.h>
#include<stdio.h>
#include<windows.h>
#include <time.h>
using namespace std;
#define N 400
float a[N][N];
struct b{
int begin;
int end;
};
DWORD WINAPI thread(LPVOID p)
{
b b_t = *(b*)p;
for(int i=0;i<N;i++)
for(int j=b_t.begin;j<b_t.end;j++)
{
a[i][j] = 0;
for(int k=0;k<i;k++)
a[i][j]+=k*sin(j)-j*cos(k);
}
return (0);
}
int main()
{
clock_t t;
HANDLE hn[2];
b b_t[3];
b_t[0].begin = 0;
b_t[0].end = N;
b_t[1].begin = 0;
b_t[1].end = N/2;
b_t[2].begin = N/2;
b_t[2].end = N;
t = clock();
thread(&b_t[0]);
printf("0 - %d\n",clock()-t);
t = clock();
hn[0] = CreateThread ( NULL, 0, thread, &b_t[0], 0, NULL);
WaitForSingleObject(hn[0], INFINITE );
printf("1 - %d\n",clock()-t);
t = clock();
hn[0] = CreateThread ( NULL, 0, thread, &b_t[1], 0, NULL);
hn[1] = CreateThread ( NULL, 0, thread, &b_t[2], 0, NULL);
WaitForMultipleObjects(2, hn, TRUE, INFINITE );
printf("2 - %d\n",clock()-t);
return 0;
}
时间:
0 - 6868
1 - 3362
2 - 1827
CPU - 酷睿 2 双核 T9300
操作系统 - Windows 8、64 位
编译器:mingw32-g++.exe,gcc版本4.6.2
编辑:
尝试了不同的顺序,结果相同,甚至尝试了不同的应用程序。 任务管理器显示函数和 1 个线程的 CPU 使用率约为 50%,2 个线程的 CPU 使用率约为 100%
每次调用后所有元素之和都一样:3189909.237955
Cygwin 结果:2.5、2.5 和 2.5 秒 Linux 结果(pthread):3.7、3.7 和 2.1 秒
@borisbn 结果:0 - 1446 1 - 1439 2 - 721。
最佳答案
差异是数学库中某些实现 sin() 和 cos() 的结果 - 如果您将对这些函数的调用替换为其他需要时间步骤与 0 和步骤 1 之间的显着差异消失。
请注意,我看到了与 gcc (tdm-1) 4.6.1 的区别,后者是针对 32 位二进制文件的 32 位工具链。优化没有区别(这并不奇怪,因为它似乎是数学库中的东西)。
但是,如果我使用 gcc (tdm64-1) 4.6.1 构建,这是一个 64 位工具链,则差异不会出现 - 无论build 正在创建 32 位程序(使用 -m32 选项)或 64 位程序(-m64)。
下面是一些示例测试运行(我对源代码做了一些小修改以使其与 C99 兼容):
使用 32 位 TDM MinGW 4.6.1 编译器:
C:\temp>gcc --version
gcc (tdm-1) 4.6.1
C:\temp>gcc -m32 -std=gnu99 -o test.exe test.c
C:\temp>test
0 - 4082
1 - 2439
2 - 1238
使用 64 位 TDM 4.6.1 编译器:
C:\temp>gcc --version
gcc (tdm64-1) 4.6.1
C:\temp>gcc -m32 -std=gnu99 -o test.exe test.c
C:\temp>test
0 - 2506
1 - 2476
2 - 1254
C:\temp>gcc -m64 -std=gnu99 -o test.exe test.c
C:\temp>test
0 - 3031
1 - 3031
2 - 1539
更多信息:
32 位 TDM 发行版 (gcc (tdm-1) 4.6.1) 链接到 中的 通过提供的导入库的系统 DLL:sin()/cos() 实现msvcrt.dll
c:/mingw32/bin/../lib/gcc/mingw32/4.6.1/../../../libmsvcrt.a(dcfls00599.o)
0x004a113c _imp__cos
虽然 64 位分发版 (gcc (tdm64-1) 4.6.1) 似乎没有这样做,而是链接到分发版提供的一些静态库实现:
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.6.1/../../../../x86_64-w64-mingw32/lib/../lib32/libmingwex.a(lib32_libmingwex_a-cos.o)
C:\Users\mikeb\AppData\Local\Temp\cc3pk20i.o (cos)
更新/结论:
在调试器中逐步探索 msvcrt.dll 的 cos() 实现程序集后,我发现时间上的差异主线程与显式创建线程的区别是由于 FPU 的精度被设置为非默认设置(可能是有问题的 MinGW 运行时在启动时这样做)。在 thread() 函数花费两倍时间的情况下,FPU 设置为 64 位精度(REAL10 或在 MSVC 中为 _PC_64)。当 FPU 控制字不是 0x27f(默认状态?)时,msvcrt.dll 运行时将在 sin() 和 中执行以下步骤cos() 函数(可能还有其他浮点函数):
fsin/fcos操作如果 FPU 控制字已设置为预期/所需的 0x27f 值,则跳过 FPU 控制字的保存/恢复。显然,保存/恢复 FPU 控制字的成本很高,因为它似乎使函数花费的时间加倍。
您可以通过在调用thread() 之前将以下行添加到main() 来解决问题:
_control87( _PC_53, _MCW_PC); // requires <float.h>
关于c++ - 为什么一个线程比调用一个函数更快,mingw,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14329214/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput