std::async 导致分段错误(或缓慢)
std::async is causing segmentation fault (or slow)
我写了简单的class来求解线性方程组,并行化我使用的矩阵行减法std::async。在 10x10 矩阵的大小之后,程序由于分段错误而崩溃。
我的第一个实现是将 vecSub((mat[c]), (temp));
替换为 std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp))
但后来发现如果我们不将其分配给任何变量,则调用析构函数并调用 .get() ,并停止主线程(是它变慢的原因),所以我将其更改为以下实现,现在我遇到了段错误
这是单线程的:
class solver
{
Mat mat;
public:
//give eqn in the form ax1+ax2+ax3..axN = k (coeffiants only)
Vec solve(Mat &in)
{
mat = in;
ge(mat);
return (bs(mat));
}
Vec solve(Mat &&in)
{
mat = std::move(in);
ge(mat);
return (bs(mat));
}
private:
void ge(Mat &mat)
{
using li = long int;
for (li p = 0; p < mat[0].size() - 1; p++)
{
for (li c = p + 1; c < mat.size(); c++)
{
auto x = mat[c][p] / mat[p][p];
auto temp = mat[p];
vecMul(x, temp);
vecSub((mat[c]), (temp));
}
}
}
Vec bs(Mat &mat)
{
using li = long int;
Vec x(mat.size());
for (li i = mat.size() - 1; i >= 0; i--)
{
double s = 0;
for (li j = i; j < mat[0].size() - 1; j++)
{
s += mat[i][j] * x[j];
x[i] = ((mat[i][mat[0].size() - 1] - s) / (mat[i][i]));
}
}
return x;
}
static void vecMul(double a, Vec &b)
{
using li = size_t;
for (li i = 0; i < b.size(); i++)
b[i] *= a;
}
//static
static void vecAdd(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] + b[i];
}
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
};
多线程
class solver
{
Mat mat;
public:
//give eqn in the form ax1+ax2+ax3..axN = k (coeffiants only)
Vec solve(Mat &in)
{
mat = in;
ge(mat);
return (bs(mat));
}
Vec solve(Mat &&in)
{
mat = std::move(in);
ge(mat);
return (bs(mat));
}
private:
void ge(Mat &mat)
{
using li = long int;
for (li p = 0; p < mat[0].size() - 1; p++)
{
std::vector<std::future<void>> ts;
for (li c = p + 1; c < mat.size(); c++)
{
auto x = mat[c][p] / mat[p][p];
auto temp = mat[p];
vecMul(x, temp);
ts.push_back(std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp)));
}
for (auto &t : ts)
{
t.get();
}
}
}
Vec bs(Mat &mat)
{
using li = long int;
Vec x(mat.size());
for (li i = mat.size() - 1; i >= 0; i--)
{
double s = 0;
for (li j = i; j < mat[0].size() - 1; j++)
{
s += mat[i][j] * x[j];
x[i] = ((mat[i][mat[0].size() - 1] - s) / (mat[i][i]));
}
}
return x;
}
static void vecMul(double a, Vec &b)
{
using li = size_t;
for (li i = 0; i < b.size(); i++)
b[i] *= a;
}
//static
static void vecAdd(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] + b[i];
}
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
// assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
};
分段发生在
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
无论 Mat
类型是什么,我都非常确定:
auto temp = mat[p];
创建的不是引用,而是副本。意思是这个
ts.push_back(std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp)));`
实际上引用了一个临时值 temp
,该值将在此循环结束时被销毁。那是未定义的行为。
这可能会解决问题:
auto& temp = mat[p];
我写了简单的class来求解线性方程组,并行化我使用的矩阵行减法std::async。在 10x10 矩阵的大小之后,程序由于分段错误而崩溃。
我的第一个实现是将 vecSub((mat[c]), (temp));
替换为 std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp))
但后来发现如果我们不将其分配给任何变量,则调用析构函数并调用 .get() ,并停止主线程(是它变慢的原因),所以我将其更改为以下实现,现在我遇到了段错误
这是单线程的:
class solver
{
Mat mat;
public:
//give eqn in the form ax1+ax2+ax3..axN = k (coeffiants only)
Vec solve(Mat &in)
{
mat = in;
ge(mat);
return (bs(mat));
}
Vec solve(Mat &&in)
{
mat = std::move(in);
ge(mat);
return (bs(mat));
}
private:
void ge(Mat &mat)
{
using li = long int;
for (li p = 0; p < mat[0].size() - 1; p++)
{
for (li c = p + 1; c < mat.size(); c++)
{
auto x = mat[c][p] / mat[p][p];
auto temp = mat[p];
vecMul(x, temp);
vecSub((mat[c]), (temp));
}
}
}
Vec bs(Mat &mat)
{
using li = long int;
Vec x(mat.size());
for (li i = mat.size() - 1; i >= 0; i--)
{
double s = 0;
for (li j = i; j < mat[0].size() - 1; j++)
{
s += mat[i][j] * x[j];
x[i] = ((mat[i][mat[0].size() - 1] - s) / (mat[i][i]));
}
}
return x;
}
static void vecMul(double a, Vec &b)
{
using li = size_t;
for (li i = 0; i < b.size(); i++)
b[i] *= a;
}
//static
static void vecAdd(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] + b[i];
}
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
};
多线程
class solver
{
Mat mat;
public:
//give eqn in the form ax1+ax2+ax3..axN = k (coeffiants only)
Vec solve(Mat &in)
{
mat = in;
ge(mat);
return (bs(mat));
}
Vec solve(Mat &&in)
{
mat = std::move(in);
ge(mat);
return (bs(mat));
}
private:
void ge(Mat &mat)
{
using li = long int;
for (li p = 0; p < mat[0].size() - 1; p++)
{
std::vector<std::future<void>> ts;
for (li c = p + 1; c < mat.size(); c++)
{
auto x = mat[c][p] / mat[p][p];
auto temp = mat[p];
vecMul(x, temp);
ts.push_back(std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp)));
}
for (auto &t : ts)
{
t.get();
}
}
}
Vec bs(Mat &mat)
{
using li = long int;
Vec x(mat.size());
for (li i = mat.size() - 1; i >= 0; i--)
{
double s = 0;
for (li j = i; j < mat[0].size() - 1; j++)
{
s += mat[i][j] * x[j];
x[i] = ((mat[i][mat[0].size() - 1] - s) / (mat[i][i]));
}
}
return x;
}
static void vecMul(double a, Vec &b)
{
using li = size_t;
for (li i = 0; i < b.size(); i++)
b[i] *= a;
}
//static
static void vecAdd(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] + b[i];
}
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
// assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
};
分段发生在
static void vecSub(Vec &a, Vec &b)
{
using li = size_t;
assert(a.size() == b.size());
for (li i = 0; i < a.size(); i++)
a[i] = a[i] - b[i];
}
无论 Mat
类型是什么,我都非常确定:
auto temp = mat[p];
创建的不是引用,而是副本。意思是这个
ts.push_back(std::async(std::launch::async, vecSub, std::ref(mat[c]), std::ref(temp)));`
实际上引用了一个临时值 temp
,该值将在此循环结束时被销毁。那是未定义的行为。
这可能会解决问题:
auto& temp = mat[p];