C++中多线程的困惑
Confusion in Multithreading in C++
我正在尝试模拟一个概率问题,其中有 n 个客户端和 n 个服务器。每个客户端随机向任何服务器发送请求,因此每个服务器可以接收任意数量的请求,我必须计算任何服务器可以接收的最大请求数。
我试图通过 运行ning 10,000 次迭代来模拟这一点,在每次迭代中,每个客户端选择一个随机服务器并向其发送请求,服务器表示为大小为 N 的整数数组。
客户端选择一个随机数,然后递增服务器数组中该索引处的值。
因为,为了获得更好的结果,问题说 N 应该约为 106.
所以为了让它快一点,我使用了多线程,其中每个线程 运行s 100 次迭代,总共有 10 个线程。
但是多线程代码产生的结果与普通代码产生的结果截然不同。
下面是代码片段以及它们的输出
普通版
#include <iostream>
#include <random>
#include <chrono>
#define N 1000000
#define iterations 1000
int servers[N];
// This array's i'th index will contain count of in how many
// iterations was i the maximum number of requests received by any server
int distr[N+1]={0};
int main(int argc, char const *argv[])
{
// Initialising
auto start = std::chrono::high_resolution_clock::now();
std::srand(time(NULL));
// Performing iterations
for(int itr=1; itr<=iterations; itr++)
{
for(int i=0;i<N;i++)
{
servers[i]=0;
}
for(int i=1;i<=N;i++)
{
int index = std::rand()%N;
servers[index]++;
}
int maxRes = -1;
for(int i=0;i<N;i++)
{
maxRes = std::max(maxRes, servers[i]);
}
distr[maxRes]+=1;
}
for(int i=0;i<=15;i++)
{
std::cout<<(double)distr[i]<<std::endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout<<duration.count()<<" milliseconds"<<std::endl;
return 0;
}
输出
0
0
0
0
0
0
0
359
552
79
10
0
0
0
0
0
1730 milliseconds
多线程版本
#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <fstream>
#define N 100000
#define iterations 1000
#define threads 10
// This array's i'th index will contain count of in how many
// iterations was i the maximum number of requests received by any server
std::atomic<int> distr[N] = {};
void execute(int number)
{
// Performing iterations
int servers[N]={0};
for(int itr=1; itr<=number; itr++)
{
for(int i=1;i<=N;i++)
{
int index = std::rand()%N;
servers[index]++;
}
int maxRes = -1;
for(int i=0;i<N;i++)
{
maxRes = std::max(maxRes, servers[i]);
servers[i]=0;
}
distr[maxRes] += 1;
}
}
int main(int argc, char const *argv[])
{
// Initialising
auto start = std::chrono::high_resolution_clock::now();
std::srand(time(NULL));
std::thread t[threads];
for(int i=0;i<threads;i++)
{
t[i] = std::thread(execute, iterations/threads);
}
for(int i=0;i<threads;i++)
{
t[i].join();
}
for(int i=0;i<=15;i++)
{
double temp = (double)distr[i];
std::cout<<i<<"\t"<<distr[i]<<std::endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout<<duration.count()<<" milliseconds"<<std::endl;
return 0;
}
输出
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 7
8 201
9 421
10 267
11 68
12 2
13 2
14 4
15 0
1385 milliseconds
虽然我有很多次 运行 正常代码,每次计数最大值 = 9 > 500,并且没有太多数据分散,我的意思是只有最大值 = 8,9,10 ,11 具有显着值其余均为零。
谁能解释一下我做错了什么?
提前致谢!
我没看到"very different results",它们只是有些不同,所以看起来有点微妙。我注意到您没有单独播种每个线程 - 这可能与它有关。
PS:如果您想要均匀分布,则不应使用 rand() % N
。为什么?参见 Stephen Lavaveij 的 this explanation。正如评论者所建议的那样,当 N
很小时,偏差可能很小,但仍然如此。
我正在尝试模拟一个概率问题,其中有 n 个客户端和 n 个服务器。每个客户端随机向任何服务器发送请求,因此每个服务器可以接收任意数量的请求,我必须计算任何服务器可以接收的最大请求数。
我试图通过 运行ning 10,000 次迭代来模拟这一点,在每次迭代中,每个客户端选择一个随机服务器并向其发送请求,服务器表示为大小为 N 的整数数组。
客户端选择一个随机数,然后递增服务器数组中该索引处的值。 因为,为了获得更好的结果,问题说 N 应该约为 106.
所以为了让它快一点,我使用了多线程,其中每个线程 运行s 100 次迭代,总共有 10 个线程。
但是多线程代码产生的结果与普通代码产生的结果截然不同。 下面是代码片段以及它们的输出
普通版
#include <iostream>
#include <random>
#include <chrono>
#define N 1000000
#define iterations 1000
int servers[N];
// This array's i'th index will contain count of in how many
// iterations was i the maximum number of requests received by any server
int distr[N+1]={0};
int main(int argc, char const *argv[])
{
// Initialising
auto start = std::chrono::high_resolution_clock::now();
std::srand(time(NULL));
// Performing iterations
for(int itr=1; itr<=iterations; itr++)
{
for(int i=0;i<N;i++)
{
servers[i]=0;
}
for(int i=1;i<=N;i++)
{
int index = std::rand()%N;
servers[index]++;
}
int maxRes = -1;
for(int i=0;i<N;i++)
{
maxRes = std::max(maxRes, servers[i]);
}
distr[maxRes]+=1;
}
for(int i=0;i<=15;i++)
{
std::cout<<(double)distr[i]<<std::endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout<<duration.count()<<" milliseconds"<<std::endl;
return 0;
}
输出
0
0
0
0
0
0
0
359
552
79
10
0
0
0
0
0
1730 milliseconds
多线程版本
#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <fstream>
#define N 100000
#define iterations 1000
#define threads 10
// This array's i'th index will contain count of in how many
// iterations was i the maximum number of requests received by any server
std::atomic<int> distr[N] = {};
void execute(int number)
{
// Performing iterations
int servers[N]={0};
for(int itr=1; itr<=number; itr++)
{
for(int i=1;i<=N;i++)
{
int index = std::rand()%N;
servers[index]++;
}
int maxRes = -1;
for(int i=0;i<N;i++)
{
maxRes = std::max(maxRes, servers[i]);
servers[i]=0;
}
distr[maxRes] += 1;
}
}
int main(int argc, char const *argv[])
{
// Initialising
auto start = std::chrono::high_resolution_clock::now();
std::srand(time(NULL));
std::thread t[threads];
for(int i=0;i<threads;i++)
{
t[i] = std::thread(execute, iterations/threads);
}
for(int i=0;i<threads;i++)
{
t[i].join();
}
for(int i=0;i<=15;i++)
{
double temp = (double)distr[i];
std::cout<<i<<"\t"<<distr[i]<<std::endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout<<duration.count()<<" milliseconds"<<std::endl;
return 0;
}
输出
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 7
8 201
9 421
10 267
11 68
12 2
13 2
14 4
15 0
1385 milliseconds
虽然我有很多次 运行 正常代码,每次计数最大值 = 9 > 500,并且没有太多数据分散,我的意思是只有最大值 = 8,9,10 ,11 具有显着值其余均为零。
谁能解释一下我做错了什么?
提前致谢!
我没看到"very different results",它们只是有些不同,所以看起来有点微妙。我注意到您没有单独播种每个线程 - 这可能与它有关。
PS:如果您想要均匀分布,则不应使用 rand() % N
。为什么?参见 Stephen Lavaveij 的 this explanation。正如评论者所建议的那样,当 N
很小时,偏差可能很小,但仍然如此。