Hi Mat,
This solution was working fine and I was able to run lots of performance tests with amazing results.
Now I have tried the same with a real world example from my company. Some small libraries.
Its central point was a simple loop.
Doing it in serial, everything is working well.
std::for_each(stationen.begin(), stationen.end(),
(ApplicationsPaar& ap) { CalculationBase(ap); });
Doing it in parallel, either “par” or “par_unseq”, the source code was compiled and linked into static libraries.
std::for_each(std::execution::par, stationen.begin(), stationen.end(),
(ApplicationsPaar& ap) { CalculationBase(ap); });
But calling them from a simple application leads to an error.
nvlink error : Undefined reference to ‘_ZN7StationDIEv’ in ‘hostpwd/ …
Looks like undefined symbols.
So I have checked the static library with “nm”.
Yes, these symbols are really undefined.
What’s going wrong here?
Both with serial loop and with parallel loop libraries are compiling and linking without any message.
But in the case of parallel loop this was not correct. There are undefined symbols.
Is it a problem with the method called? Following your documentation, a static method with a reference to a simple class as argument is allowed for parallel processes on GPU.
And in my former examples this idea was working well.
But not here, so I am confused.
The header-file:
class MY_LIB_PUBLIC CalculatorBase
{
public:
CalculatorBase();
CalculatorBase(const CalculatorBase& toCopy);
virtual ~CalculatorBase();
CalculatorBase& operator =(const CalculatorBase& av);
protected:
void copyAttributes(const CalculatorBase& av);
public:
void CalculationBaseSeriell();
void CalculationBaseParallelCPU();
void CalculationBaseParallelGPU();
void CalculationIM();
public:
static void CalculationBase(ApplicationsPaar& AP);
public:
std::vector stationen;
};
And the relevant cpp-part. Simple distance predictions hidden behind an *-operator, marked in yellow.
void CalculatorBase::CalculationBase(ApplicationsPaar& stationen)
{
int i, ni;
int s, n_s = stationen.S.STATION.size();
int g, n_g = stationen.G.STATION.size();
for (s = 0; s < n_s; s++)
{
Station S = stationen.S.STATION[s];
GeometrieBasis* GBs = NULL;
if (S.sitePoint != NULL)
{
GBs = new GeometrieDatenKreis();
((GeometrieDatenKreis)GBs).S.Laenge_grad = S.sitePoint->SID_int_DECIMAL;
((GeometrieDatenKreis)GBs).S.Breite_grad = S.sitePoint->SID_LAT_DECIMAL;
((GeometrieDatenKreis)GBs).r_m = 0.0;
}
else if (S.siteCircle != NULL)
{
GBs = new GeometrieDatenKreis();
((GeometrieDatenKreis)GBs).S.Laenge_grad = S.siteCircle->SID_int_DECIMAL;
((GeometrieDatenKreis)GBs).S.Breite_grad = S.siteCircle->SID_LAT_DECIMAL;
((GeometrieDatenKreis)GBs).r_m = S.siteCircle->ST_AREA_RADIUS;
}
else if (S.siteVector != NULL)
{
switch (S.siteVector->SID_TYPE)
{
case SiteVector::Type::closed:
ni = S.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenKontur();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = S.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = S.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenKontur)GBs).PL.PL.push_back(GK);
}
break;
case SiteVector::Type::list:
ni = S.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenPunktListe();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = S.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = S.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenPunktListe)GBs).PL.PL.push_back(GK);
}
((GeometrieDatenPunktListe)GBs).r_m = 0.0;
break;
case SiteVector::Type::open:
ni = S.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenPolygon();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = S.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = S.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenPolygon)GBs).PL.PL.push_back(GK);
}
break;
}
}
Geometrie Gs;
Gs.pSDB = GBs;
for (g = 0; g < n_g; g++)
{
Station G = stationen.G.STATION[g];
GeometrieBasis* GBg = NULL;
if (G.sitePoint != NULL)
{
GBg = new GeometrieDatenKreis();
((GeometrieDatenKreis)GBg).S.Laenge_grad = G.sitePoint->SID_int_DECIMAL;
((GeometrieDatenKreis)GBg).S.Breite_grad = G.sitePoint->SID_LAT_DECIMAL;
((GeometrieDatenKreis)GBg).r_m = 0.0;
}
else if (G.siteCircle != NULL)
{
GBg = new GeometrieDatenKreis();
((GeometrieDatenKreis)GBg).S.Laenge_grad = G.siteCircle->SID_int_DECIMAL;
((GeometrieDatenKreis)GBg).S.Breite_grad = G.siteCircle->SID_LAT_DECIMAL;
((GeometrieDatenKreis)GBg).r_m = G.siteCircle->ST_AREA_RADIUS;
}
else if (G.siteVector != NULL)
{
switch (G.siteVector->SID_TYPE)
{
case SiteVector::Type::closed:
ni = G.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenKontur();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = G.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = G.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenKontur)GBg).PL.PL.push_back(GK);
}
break;
case SiteVector::Type::list:
ni = G.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenPunktListe();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = G.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = G.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenPunktListe)GBg).PL.PL.push_back(GK);
}
((GeometrieDatenPunktListe)GBs).r_m = 0.0;
break;
case SiteVector::Type::open:
ni = G.siteVector->SID_VECTOR.size();
GBs = new GeometrieDatenPolygon();
for (i = 0; i < ni; i++)
{
GeoKoordinate GK;
GK.Laenge_grad = G.siteVector->SID_VECTOR[i].SID_int_DECIMAL;
GK.Breite_grad = G.siteVector->SID_VECTOR[i].SID_LAT_DECIMAL;
((GeometrieDatenPolygon)GBg).PL.PL.push_back(GK);
}
break;
}
}
Geometrie Gg;
Gg.pSDB = GBg;
stationen.Abstandsmatrix[s][g] = Gs * Gg;
}
}
}
Best wishes
Uli