Вопрос

РЕДАКТИРОВАТЬ: Я могу запустить одну и ту же программу дважды одновременно без каких-либо проблем. Как я могу продублировать это с помощью OpenMP или каким-либо другим методом?

Это основная структура проблемы.

//Defined elsewhere
class SomeClass
{
public:
  void Function()
  {
    // Allocate some memory
    float *Data;
    Data = new float[1024];

    // Declare a struct which will be used by functions defined in the DLL
    SomeStruct Obj;
    Obj = MemAllocFunctionInDLL(Obj);

    // Call it
    FunctionDefinedInDLL(Data,Obj);

    // Clean up
    MemDeallocFunctionInDLL(Obj);
    delete [] Data;        
  }
}

void Bar()
{
   #pragma omp parallel for
   for(int j = 0;j<10;++j)
   {
     SomeClass X;
     X.Function();
   }
}

Я проверил, что при попытке освободить часть памяти через MemDeallocFunctionInDLL(), _CrtIsValidHeapPointer() утверждение терпит неудачу.

Это потому, что оба потока пишут в одну и ту же память?

Итак, чтобы это исправить, я решил сделать SomeClass личное (это мне совершенно чуждо, поэтому любая помощь приветствуется).

void Bar()
{
   SomeClass X;
   #pragma omp parallel for default(shared) private(X)
   for(int j = 0;j<10;++j)
   {         
     X.Function();
   }
}

И сейчас он терпит неудачу, когда пытается выделять память в начале для Data.

Примечание: При необходимости могу внести изменения в DLL.

Примечание: Он прекрасно работает без #pragma omp parallel for

РЕДАКТИРОВАТЬ: Сейчас Bar выглядит так:

void Bar()
{
   int j
   #pragma omp parallel for default(none) private(j)
   for(j = 0;j<10;++j)
   {
     SomeClass X;         
     X.Function();
   }
}

Все еще не повезло.

Это было полезно?

Решение

Ознакомьтесь с MemAllocFunctionInDLL, FunctionDefinedInDLL, MemDeallocFunctionInDLL. потокобезопасный, или вновь поступающий.Другими словами, являются ли эти функции статическими переменными или общими переменными?В таком случае вам необходимо убедиться, что эти переменные не повреждены другими потоками.

Тот факт, что без omp-for все в порядке, может означать, что вы неправильно написали некоторые функции для обеспечения потокобезопасности.

Я хотел бы посмотреть, какие функции выделения/освобождения памяти использовались в Mem(Alloc|Dealloc)FunctionInDLL.

Добавлен:Я почти уверен, что ваши функции в DLL не являются потокобезопасными.Вы можете без проблем запускать эту программу одновременно.Да, все должно быть в порядке, если только ваша программа не использует общесистемные общие ресурсы (такие как глобальная память или общая память между процессами), что случается очень редко.В этом случае в потоках нет общих переменных, поэтому ваша программа работает нормально.

Но вызов этих функций в многопоточность (то есть в одном процессе) приводит к сбою вашей программы.Это означает, что в потоках есть некоторые общие переменные, и они могли быть повреждены.

Это не проблема OpenMP, а просто ошибка многопоточности.Эту проблему можно было бы решить просто.Пожалуйста, проверьте функции DLL, можно ли их одновременно вызывать из многих потоков.

Как приватизировать статические переменные

Допустим, у нас есть такие глобальные переменные:

static int  g_data;
static int* g_vector = new int[100];

Приватизация – это не что иное, как создание частный копия для каждой темы.

int  g_data[num_threads];
int* g_vector[num_threads];
for (int i = 0; i < num_threads; ++i)
  g_vector[i] = new int[100];

И тогда любые ссылки на такие переменные

// Thread: tid
g_data[tid] = ...
.. = g_vector[tid][..]

Да, это довольно просто.Однако этот вид кода может иметь ложный обмен проблема.Но ложное разделение — это вопрос производительности, а не правильности.

Во-первых, просто попробуйте приватизировать любые статические и глобальные переменные.Затем проверьте его правильность.Затем посмотрите, какое ускорение вы получите.Если ускорение масштабируемо (скажем, в 3,7 раза быстрее на четырехъядерном процессоре), то все в порядке.Но в случае низкого ускорения (например, двукратного ускорения на четырехъядерном процессоре) вы, вероятно, столкнетесь с проблемой ложного разделения.Чтобы решить проблему ложного совместного использования, все, что вам нужно сделать, это просто добавить некоторые дополнения в структуры данных.

Другие советы

Вместо

delete Data

ты должен написать

delete [] Data;

Где бы вы ни делали new [], обязательно используйте delete [].

Похоже, ваша проблема не специфична для openmp.Вы пытались запустить приложение без включения #pragma Parallel?

default(shared) означает, что все переменные совместно используются потоками, а это не то, что вам нужно.Измените это на значение по умолчанию (нет).

Private(X) создаст копию X для каждого потока, однако ни один из них не будет инициализирован, поэтому не обязательно выполнять какую-либо конструкцию.

Я думаю, вам лучше использовать свой первоначальный подход: поставить точку останова в вызове Dealloc и посмотреть, что такое указатель памяти и что он содержит.Вы можете увидеть защитные байты чтобы определить, была ли память перезаписана в конце одного вызова или после потока.

Кстати, я предполагаю, что это сработает, если вы запустите его один раз, без цикла omp?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top