Nguyên nhân có thể xảy ra nhất đối với hành vi này là giới hạn kích thước ngăn xếp của bạn quá nhỏ (vì bất kỳ lý do gì). Vì e_in
là riêng tư cho mỗi chuỗi OpenMP, một bản sao cho mỗi luồng được phân bổ trên ngăn xếp luồng (ngay cả khi bạn đã chỉ định -heap-arrays
!). 202000
yếu tố của REAL(KIND=8)
mất 1616 kB (hoặc 1579 KiB).
Kích thước giới hạn ngăn xếp có thể được điều khiển bởi một số cơ chế:
Mở vỏ hệ thống Unix chuẩn số lượng ngăn xếp kích thước được điều khiển bởi ulimit -s <stacksize in KiB>
. Đây cũng là giới hạn kích thước ngăn xếp cho luồng OpenMP chính. Giá trị của giới hạn này cũng được sử dụng bởi thư viện chủ đề POSIX (pthreads
) làm kích thước ngăn xếp mặc định khi tạo chuỗi mới.
OpenMP hỗ trợ kiểm soát giới hạn kích thước ngăn xếp của tất cả bổ sung chủ đề qua biến môi trường OMP_STACKSIZE
. Giá trị của nó là một số có hậu tố tùy chọn k
/K
cho KiB, m
/M
ffor MiB hoặc g
/G
cho GiB. Giá trị này không ảnh hưởng đến kích thước ngăn xếp của chuỗi chính.
Thời gian chạy GNU OpenMP (libgomp
) nhận ra biến môi trường không chuẩn GOMP_STACKSIZE
. Nếu đặt giá trị này ghi đè giá trị OMP_STACKSIZE
.
Thời gian chạy Intel OpenMP nhận ra biến môi trường không chuẩn KMP_STACKSIZE
. Nếu đặt giá trị này ghi đè giá trị OMP_STACKSIZE
và cũng ghi đè giá trị GOMP_STACKSIZE
nếu thời gian chạy OpenMP tương thích được sử dụng (mặc định là thư viện thời gian chạy Intel OpenMP hiện có duy nhất là compat
).
Nếu không có biến số *_STACKSIZE
nào được đặt, mặc định cho thời gian chạy Intel OpenMP là 2m
trên kiến trúc 32 bit và 4m
trên các bit 64 bit.
Trên Windows, kích thước ngăn xếp của sợi chính là một phần của tiêu đề PE và được nhúng bởi trình liên kết. Nếu sử dụng LINK
của Microsoft để thực hiện liên kết, kích thước được chỉ định bằng cách sử dụng /STACK:reserve[,commit]
. Đối số reserve
chỉ định kích thước ngăn xếp tối đa theo byte trong khi đối số tùy chọn commit
chỉ định kích thước cam kết ban đầu. Cả hai có thể được chỉ định dưới dạng giá trị thập lục phân sử dụng tiền tố 0x
.Nếu việc liên kết lại tệp thực thi không phải là một tùy chọn, kích thước ngăn xếp có thể được sửa đổi bằng cách chỉnh sửa tiêu đề PE với EDITBIN
. Nó có cùng một đối số liên quan đến stack với tư cách là trình liên kết. Các chương trình được biên dịch với toàn bộ chương trình tối ưu hóa của MSVC được bật (/GL
) không thể chỉnh sửa được.
Trình liên kết GNU dành cho mục tiêu Win32 hỗ trợ đặt kích thước ngăn xếp qua đối số --stack
. Để chuyển tùy chọn trực tiếp từ GCC, có thể sử dụng -Wl,--stack,<size in bytes>
.
Lưu ý rằng ngăn xếp chủ đề đang thực sự phân bổ với kích thước được thiết lập bởi *_STACKSIZE
(hoặc giá trị mặc định), không giống như chồng các chủ đề chính, mà bắt đầu nhỏ và sau đó phát triển theo yêu cầu đến hộp set giới hạn. Vì vậy, không đặt *_STACKSIZE
thành giá trị lớn tùy ý nếu không bạn có thể đạt đến giới hạn kích thước bộ nhớ ảo của quá trình.
Dưới đây là một số ví dụ:
$ ifort -openmp my_module.f90 main.f90
Đặt giới hạn chính ngăn xếp kích thước đến 1 MiB (thread OpenMP bổ sung sẽ nhận được 4 MiB theo mặc định):
$ ulimit -s 1024
$ ./a.out
zsh: segmentation fault (core dumped) ./a.out
Đặt stack chính giới hạn kích thước đến 1700 KiB:
$ ulimit -s 1700
$ ./a.out
0.000000000000000E+000
(0.000000000000000E+000,0.000000000000000E+000)
0.000000000000000E+000
(0.000000000000000E+000,0.000000000000000E+000)
Đặt giới hạn kích thước ngăn xếp chính thành 2 MiB và kích thước ngăn xếp của Chủ đề dditional tới 1 MiB:
$ ulimit -s 2048
$ KMP_STACKSIZE=1m ./a.out
zsh: segmentation fault (core dumped) KMP_STACKSIZE=1m ./a.out
Trên hầu hết các hệ thống Unix giới hạn kích thước ngăn xếp của các chủ đề chính được thiết lập bởi PAM hoặc cơ chế đăng nhập khác (xem /etc/security/limits.conf
). Mặc định trên Scientific Linux 6.3 là 10 MiB.
Một trường hợp khác có thể dẫn đến lỗi là nếu giới hạn không gian địa chỉ ảo được đặt quá thấp. Ví dụ, nếu giới hạn không gian địa chỉ ảo là 1 GiB và giới hạn kích thước ngăn xếp luồng được đặt là 512 MiB, thì thời gian chạy OpenMP sẽ cố gắng phân bổ 512 MiB cho mỗi chuỗi bổ sung. Với hai chủ đề sẽ có 1 GiB cho ngăn xếp, và khi không gian cho mã, thư viện được chia sẻ, heap, vv được thêm lên, kích thước bộ nhớ ảo sẽ phát triển vượt quá 1 GiB và một lỗi sẽ xảy ra:
Đặt giới hạn không gian địa chỉ ảo tới 1 GiB và chạy với hai chủ đề bổ sung với 512 đống MiB (tôi đã nhận xét ra các cuộc gọi đến omp_set_num_threads()
):
$ ulimit -v 1048576
$ KMP_STACKSIZE=512m OMP_NUM_THREADS=3 ./a.out
OMP: Error #34: System unable to allocate necessary resources for OMP thread:
OMP: System error #11: Resource temporarily unavailable
OMP: Hint: Try decreasing the value of OMP_NUM_THREADS.
forrtl: error (76): Abort trap signal
... trace omitted ...
zsh: abort (core dumped) OMP_NUM_THREADS=3 KMP_STACKSIZE=512m ./a.out
Trong trường hợp này OpenMP thư viện thời gian chạy sẽ thất bại trong việc tạo ra một chủ đề mới và sẽ thông báo cho bạn trước khi hủy bỏ việc chấm dứt chương trình.
tôi bị mất rằng, nghĩ rằng những mảng chỉ là 2 yếu tố.Dù sao tôi thường sử dụng -fstack-mảng với mảng lớn hơn theo đơn đặt hàng của cường độ. Nhưng không phải với Ifort. –
Có một chút khó hiểu rằng với cả 'gfortran' và' ifort' các bản sao riêng của mảng tĩnh luôn tự động và được cấp phát trên ngăn xếp luồng mặc dù có bất kỳ tùy chọn trình biên dịch nào có thể ảnh hưởng đến vị trí của các mảng thông thường. –