Спасибо за ваши ответы, особенно за подсказку об OpenMP, это действительно выполнимо. Я сделал небольшую программу, чтобы быть абсолютно уверенным. Она состоит из одной Fortran 77 части, названной в одной основной программе C++ (который является моей проблемой):
Фортран 77 подпрограмм func.f:
subroutine set(ii, jj)
implicit none
include "func.inc"
integer ii, jj
integer OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
i = ii + 1
j = jj
!$OMP CRITICAL
print *, OMP_GET_THREAD_NUM(), OMP_GET_NUM_THREADS(), i, j
!$OMP END CRITICAL
return
end
subroutine func(n, v)
implicit none
include "func.inc"
integer n, k
integer v(n)
do k = i, j
a = k + 1
b = a * a
c = k - 1
v(k) = b - c * c
enddo
return
end
с инклюдником func.inc
integer i, j
integer a, b, c
common /mycom1/ i, j
!$OMP THREADPRIVATE(/mycom1/)
common /mycom2/ a, b, c
!$OMP THREADPRIVATE(/mycom2/)
и, наконец, C++ программа main.cpp:
#include<iostream>
#include<sstream>
#include<vector>
using namespace std;
#include<omp.h>
extern "C"
{
void set_(int*, int*);
void func_(int*, int*);
};
int main(int argc, char *argv[])
{
int nthread;
{
istringstream iss(argv[1]);
iss >> nthread;
}
int n;
{
istringstream iss(argv[2]);
iss >> n;
}
vector<int> a(n, -1);
#pragma omp parallel num_threads(nthread) shared(a)
{
const int this_thread = omp_get_thread_num();
const int num_threads = omp_get_num_threads();
const int m = n/num_threads;
int start = m * this_thread;
int end = start + m;
const int p = n % num_threads;
for (int i = 0; i < this_thread; ++i)
if (p > i) start++;
for (int i = 0; i <= this_thread; ++i)
if (p > i) end++;
#pragma omp critical
{
cout << "#t " << this_thread << " : [" << start
<< ", " << end << "[" << endl;
}
set_(&start, &end);
func_(&n, a.data());
}
cout << "[ " << a[0];
for (int i = 1; i < n; ++i)
cout << ", " << a[i];
cout << "]" << endl;
ostringstream oss;
for (int i = 1; i < n; ++i)
if ((a[i] - a[i - 1]) != int(4))
oss << i << " ";
if (! oss.str().empty())
cout << "<<!! Error occured at index " << oss.str()
<< " !!>>" << endl;
return 0;
}
компиляции шаги (GCC версии 4.8.1):
gfortran -c func.f -fopenmp
g++ -c main.cpp -std=gnu++11 -fopenmp
g++ -o test main.o func.o -lgfortran -fopenmp
Вы можете запустить его следующим образом:
./test 10 1000
где
- первое целое число (10) - количество требуемых потоков,
- второй (1000) - длина одного вектора.
Цель этой программы состоит в том, чтобы разделить этот вектор между потоками и позволить каждому потоку заполнить одну его часть.
Заполнение вектора производится в течение Fortran 77:
- установить рутинных сначала устанавливает нижнюю и верхнюю границу управляется нити,
- FUNC Затем процедура заполняет вектор между предыдущая границы.
Обычно, если нет ошибок, и если общие Fortran 77 блоков не являются общими, окончательный вектор должен быть заполнен 4 * к значениям, к переходя от 1 до 1000.
I не смог поймать программу. И наоборот, если я удаляю fortran 77 OMP-директивы в func.inc, тогда общие блоки не более приватны, и возникает много ошибок.
Итак, единственное, что мне нужно сделать, чтобы решить мою первоначальную проблему, - это добавить директивы OMP сразу за любыми распространенными блоками, которые, надеюсь, не сложны, поскольку все они собраны в один файл include (например, мой тест).
Надеюсь, это поможет.
С уважением.
Это неправда, есть способы обойти. –
@ Владымир, не могли бы вы уточнить? – SergeyA
См. Мой ответ .. –