Điều này trông giống như một lỗi trong GCC, không tạo ra một hàm tạo bản sao cho std::vector<int, std::allocator<int> >
. Lưu ý rằng lỗi đến từ trình liên kết và không xảy ra trong giai đoạn biên dịch. Hàm tạo bản sao được sử dụng trong hàm sao chép khởi tạo các tham số firstprivate
của hàm tác vụ được nêu. Buộc trình biên dịch tạo ra nó, ví dụ: thay đổi
std::vector<int> a;
để
std::vector<int> a, b(a);
sửa chữa vấn đề.
Dưới đây là mô tả chi tiết hơn. GCC biến đổi đoạn mã sau
#pragma omp task shared(sum)
{
sum = recursiveSumBody(vec);
}
vào một cái gì đó như:
struct omp_data_a data_o;
data_o.vec = vec;
data_o.sum = ∑
GOMP_task(omp_fn_0, &data_o, omp_cpyfn_1, 32, 8, 1, 0, 0, 0);
// --- outlined task body ---
void omp_fn_0(struct omp_data_s & restrict data_i)
{
struct vector & vec = &data_i->vec;
*data_i->sum = recursiveSumBody<int>(vec);
std::vector<int>::~vector(vec);
}
// --- task firstprivate initialisation function ---
void omp_cpyfn_1(struct omp_data_s *data_o, struct omp_data_a *data_i)
{
data_o->sum = data_i->sum;
struct vector &d40788 = data_i->vec;
struct vector *this = &data_o->vec;
std::vector<int>::vector(this, d40788); // <--- invocation of the copy constructor
}
omp_cpyfn_1
được gọi bởi GOMP_task()
để khởi sự lập luận firstprivate. Nó gọi hàm tạo bản sao của std::vector<int>
, bởi vì (first-)private
xử lý các tham chiếu đến kiểu T là kiểu T, nhưng hàm tạo không được tạo ra, do đó mã đối tượng không liên kết. Đây có lẽ là một lỗi trong mã gimplifier như các nhà xây dựng bản sao được tạo ra khi một tổ chức phi tham khảo std::vector<T, A>
được tư nhân hóa, ví dụ, với mã như thế này:
...
std::vector<T, A> b;
#pragma omp task shared(sum)
{
sum = recursiveSumBody(b);
}
...
mã biên dịch với Intel 18.0b. Chỉ định rõ ràng vec
là firstprivate
vi phạm theo cách tương tự như với GCC (icpc phàn nàn về vec
là loại không đầy đủ). Bạn có thể sử dụng giải pháp sau:
template<typename T, typename A>
T recursiveSumBody(std::vector<T, A> &vec) {
T sum = 0;
std::vector<T, A> *ptr = &vec;
#pragma omp task shared(sum)
{
sum = recursiveSumBody(*ptr);
}
return vec[0];
}
Trong trường hợp này ptr
là con trỏ. Phiên bản firstprivate
của nó là một con trỏ trỏ đến cùng một vị trí, tức là trường hợp vectơ. Ngữ nghĩa khác với mã ban đầu vì ở đây không có bản sao riêng của toàn bộ vectơ được tạo ra, thay vào đó vector gốc được sử dụng.
Bất cứ ai đã thấy một cái gì đó như thế này? Tôi đoán tôi có thể sử dụng con trỏ đến phần tử thứ 0 của vectơ, thay vì 'std :: vector', nhưng tôi không muốn sử dụng con trỏ trực tiếp nếu có thể. –
Lưu ý rằng 'libomp-dev' là thời gian chạy LLVM OpenMP không liên quan đến' gomp', là thời gian chạy OpenMP được đóng gói bởi 'gcc'. – Zulan