Многопоточный имитационный отжиг

Я написал многопоточную программу имитации отжига, но она не работает. Я не уверен, что код правильный или нет. Код может компилироваться, но когда я запускаю код, он падает. Это просто ошибка во время выполнения.

#include <stdio.h>
#include <time.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <ctime>
#include <windows.h>
#include <process.h>

using namespace std;typedef vector<double> Layer; //defines a vector type

typedef struct {
Layer Solution1;
double temp1;
double coolingrate1;
int MCL1;
int prob1;
}t;
//void SA(Layer Solution, double temp, double coolingrate, int MCL, int prob){double  Rand_NormalDistri(double mean, double stddev) {
//Random Number from Normal Distribution

static double n2 = 0.0;
static int n2_cached = 0;
if (!n2_cached) {
// choose a point x,y in the unit circle uniformly at random
double x, y, r;
do {
//  scale two random integers to doubles between -1 and 1
x = 2.0*rand()/RAND_MAX - 1;
y = 2.0*rand()/RAND_MAX - 1;

r = x*x + y*y;
} while (r == 0.0 || r > 1.0);

{
// Apply Box-Muller transform on x, y
double d = sqrt(-2.0*log(r)/r);
double n1 = x*d;
n2 = y*d;

// scale and translate to get desired mean and standard deviation

double result = n1*stddev + mean;

n2_cached = 1;
return result;
}
} else {
n2_cached = 0;
return n2*stddev + mean;
}
}double   FitnessFunc(Layer x, int ProbNum)
{int i,j,k;
double z;
double fit = 0;
double   sumSCH;

if(ProbNum==1){
// Ellipsoidal function
for(j=0;j< x.size();j++)
fit+=((j+1)*(x[j]*x[j]));
}

else if(ProbNum==2){
// Schwefel's function
for(j=0; j< x.size(); j++)
{
sumSCH=0;

for(i=0; i<j; i++)
sumSCH += x[i];
fit += sumSCH * sumSCH;
}
}

else if(ProbNum==3){
// Rosenbrock's function

for(j=0; j< x.size()-1; j++)
fit += 100.0*(x[j]*x[j] - x[j+1])*(x[j]*x[j] - x[j+1]) + (x[j]-1.0)*(x[j]-1.0);
}
return fit;
}

double probl(double energychange, double temp){
double a;
a= (-energychange)/temp;
return double(min(1.0,exp(a)));
}

int random (int min, int max){
int n = max - min + 1;
int remainder = RAND_MAX % n;
int x;
do{
x = rand();
}while (x >= RAND_MAX - remainder);
return min + x % n;
}

//void SA(Layer Solution, double temp, double coolingrate, int MCL, int prob){
void SA(void *param){

t *args = (t*) param;

Layer Solution = args->Solution1;
double temp = args->temp1;
double coolingrate = args->coolingrate1;
int MCL = args->MCL1;
int prob = args->prob1;

double Energy;
double EnergyNew;
double EnergyChange;
Layer SolutionNew(50);

Energy = FitnessFunc(Solution, prob);

while (temp > 0.01){

for ( int i = 0; i < MCL; i++){
for (int j = 0 ; j < SolutionNew.size(); j++){

SolutionNew[j] = Rand_NormalDistri(5, 1);
}
EnergyNew = FitnessFunc(SolutionNew, prob);
EnergyChange = EnergyNew - Energy;

if(EnergyChange <= 0){
Solution = SolutionNew;
Energy = EnergyNew;
}
if(probl(EnergyChange ,temp ) >  random(0,1)){
//cout<<SolutionNew[i]<<endl;
Solution = SolutionNew;
Energy = EnergyNew;
cout << temp << "=" << Energy << endl;
}
}
temp = temp * coolingrate;
}

}int main ()
{

srand ( time(NULL) ); //seed for getting different numbers each time the prog is runLayer SearchSpace(50); //declare a vector of 20 dimensions

//for(int a = 0;a < 10; a++){

for (int i = 0 ; i < SearchSpace.size(); i++){

SearchSpace[i] = Rand_NormalDistri(5, 1);
}

t *arg1;
arg1 = (t *)malloc(sizeof(t));
arg1->Solution1 = SearchSpace;
arg1->temp1 = 1000;
arg1->coolingrate1 = 0.01;
arg1->MCL1 = 100;
arg1->prob1 = 3;

//cout << "Test " << ""<<endl;
_beginthread( SA, 0, (void*) arg1);
Sleep( 100 );

//SA(SearchSpace, 1000, 0.01, 100, 3);
//}

return 0;
}

Пожалуйста помоги.

Спасибо
Авинеш

-1

Решение

Как указывалось выше, вы используете malloc в коде C ++. Это источник вашей аварии.

Malloc выделит блок памяти, но поскольку он действительно был разработан для C, он не вызывает никаких конструкторов C ++. В этом случае вектор<двойной> никогда не строится должным образом. когда

arg1->Solution1 = SearchSpace;

Вызывается, переменная-член «Solution1» имеет неопределенное состояние и оператор присваивания завершается сбоем.

Вместо malloc попробуй

arg1 = new t;

Это выполнит примерно то же самое, но ключевое слово «new» также вызывает любые необходимые конструкторы для обеспечения вектора<двойной> правильно инициализирован.

Это также поднимает еще одну незначительную проблему, что эту память, которую вы обновили, также необходимо где-то удалить. В этом случае, так как arg1 передается другому потоку, он, вероятно, должен быть очищен как

delete args;

вашей функцией «SA» после того, как это сделано с переменной args.

2

Другие решения

Хотя я не знаю истинную причину ваших аварий, я не очень удивлен, что вы попали в беду. Например, эти «кэшированные» статические переменные в Rand_NormalDistri очевидно уязвимы для гонок данных. Почему ты не используешь std::normal_distribution? Практически всегда полезно использовать стандартные библиотечные подпрограммы, когда они доступны, и даже более того, когда нужно учитывать хитрость многопоточности.

Хуже того, вы сильно смешиваете C и C ++. malloc это то, что вы практически никогда не должны использовать в коде C ++ — он не знает о RAII, которая является одной из немногих искробезопасных вещей, за которые вы можете цепляться в C ++.

2

По вопросам рекламы [email protected]