use*_*768 6 c++ performance multithreading mingw function
当我调用函数执行时间是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;
}
Run Code Online (Sandbox Code Playgroud)
时报:
0 - 6868
1 - 3362
2 - 1827
Run Code Online (Sandbox Code Playgroud)
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位工具链,则不会出现差异- 无论构建是创建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
Run Code Online (Sandbox Code Playgroud)使用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
Run Code Online (Sandbox Code Playgroud)更多信息:
32位TDM分发(gcc(tdm-1)4.6.1)通过提供的导入库链接到系统DLL中的sin()/ cos()implements msvcrt.dll:
c:/mingw32/bin/../lib/gcc/mingw32/4.6.1/../../../libmsvcrt.a(dcfls00599.o)
0x004a113c _imp__cos
Run Code Online (Sandbox Code Playgroud)
虽然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)
Run Code Online (Sandbox Code Playgroud)
更新/结论:
在调试器中进行了一些探索后,逐步msvcrt.dll执行了cos()我的实现,我发现主线程与显式创建线程的时序差异是由于FPU的精度被设置为非默认设置(可能是MinGW运行时在启动时会这样做).在thread()函数需要两倍长的情况下,FPU设置为64位精度(REAL10或MSVC说话_PC_64).当FPU控制字不是0x27f(默认状态?)时,msvcrt.dll运行时将在sin()和cos()函数(以及可能的其他浮点函数)中执行以下步骤:
fsin/ fcos操作如果FPU控制字已经设置为预期/期望的0x27f值,则跳过保存/恢复.显然,保存/恢复FPU控制字是昂贵的,因为它似乎使函数所花费的时间加倍.
您可以通过main()在调用之前添加以下行来解决此问题thread():
_control87( _PC_53, _MCW_PC); // requires <float.h>
Run Code Online (Sandbox Code Playgroud)