C++ C+中的多线程混乱+;
我试图模拟一个概率问题,其中有n个客户端和n个服务器。每个客户端随机向任何服务器发送一个请求,因此每个服务器可以接收任意数量的请求,我必须计算任何服务器可以接收的最大请求的预期数量 我试图通过运行10000次迭代来模拟这一点,在每次迭代中,每个客户机选择一个随机服务器并向其发送一个请求,服务器被表示为大小为N的整数数组 客户端选择一个随机数,然后服务器数组中该索引处的值递增。 同样,为了得到更好的结果,问题是N应该是106左右 为了让它更快一点,我使用了多线程技术,其中每个线程运行100次迭代,总共有10个线程 但是多线程代码产生的结果与普通代码非常不同。 下面是两个代码段的输出 正常版本C++ C+中的多线程混乱+;,c++,multithreading,random,data-race,C++,Multithreading,Random,Data Race,我试图模拟一个概率问题,其中有n个客户端和n个服务器。每个客户端随机向任何服务器发送一个请求,因此每个服务器可以接收任意数量的请求,我必须计算任何服务器可以接收的最大请求的预期数量 我试图通过运行10000次迭代来模拟这一点,在每次迭代中,每个客户机选择一个随机服务器并向其发送一个请求,服务器被表示为大小为N的整数数组 客户端选择一个随机数,然后服务器数组中该索引处的值递增。 同样,为了得到更好的结果,问题是N应该是106左右 为了让它更快一点,我使用了多线程技术,其中每个线程运行100次迭代,
#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;
}
#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;
}
多线程版本
#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;
}
#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;
}
虽然我已经运行了很多次正常代码,每次最大值的计数=9>500,并且没有太多的数据分散,但我的意思是只有最大值=8,9,10,11具有有效值,其余都是零
谁能解释一下我做错了什么
提前谢谢 我看不到“非常不同的结果”,它们只是有些不同,所以看起来有点微妙。我注意到您没有单独播种每个线程-这可能与此有关
PS:如果你想要一个统一的分布,你不应该使用
rand()%N
。为什么?见斯蒂芬·拉瓦维。正如评论家所说,当代码> N>代码>时,歪曲可能很小,但是仍然。你使用互斥吗?如果你在C++编程,那么请不要添加其他语言标签。@ MohammadrezaPanahi,但是在哪一部分可以有数据竞争?对于Disr阵列,我已经在使用std::atomic?也许您试图解决的问题不像您想象的那样可并行化?如果将线程数减半或加倍,结果会有很大差异吗?哦,你的CPU有多少核?线程数超过内核数可能会使速度变慢。哦,顺便说一下,它的实现定义了线程是否安全。最好不要使用它,而是使用(例如)。如果您想要统一的分布,请不要使用rand()%N!这与其说是回答,不如说是评论。如果N
远小于RAND_MAX
,则由于RAND_MAX%N
不为零而导致的任何偏差都可以忽略不计,但实际的加密等用途除外。有能力成功编写这种类型代码的人已经知道不要这样做。你没有把每一条线分开播种为什么?多次播种std::rand()
可能是错误的。@hellow:Fixed.@AndrewHenle:你是对的,但是在OP的玩具示例中,N
可能会很慢,但它可能会改变,并且对于其他阅读此问题的人来说可能不会太低。