чтение из общей памяти - PullRequest
0 голосов
/ 07 июня 2011

Исходя из CUDA Меня интересует, как разделяемая память считывается из потока и сравнивается с требованиями выравнивания чтения CUDA.В качестве примера я буду использовать следующий код:

#include <sys/unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define THREADS 2

void * threadFun(void * args);

typedef struct {
    float * dataPtr;
    int tIdx,
    dSize;
} t_data;

int main(int argc, char * argv[])
{
    int i,
    sizeData=5;
    void * status;

    float *data;

    t_data * d;

    pthread_t * threads;
    pthread_attr_t attr;

    data=(float *) malloc(sizeof(float) * sizeData );
    threads=(pthread_t *)malloc(sizeof(pthread_t)*THREADS);
    d = (t_data *) malloc (sizeof(t_data)*THREADS);

    data[0]=0.0;
    data[1]=0.1;
    data[2]=0.2;
    data[3]=0.3;
    data[4]=0.4;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for (i=0; i<THREADS;i++)
    {
        d[i].tIdx=i;
        d[i].dataPtr=data;
        d[i].dSize=sizeData;
        pthread_create(&threads[i],NULL,threadFun,(void *)(d+i));
    }

    for (i=0; i<THREADS; i++)
    {
        pthread_join(threads[i],&status);
        if(status);
            //Error;
    }
    return 0;
}

void * threadFun(void * args)
{
    int i;

    t_data * d= (t_data *) args;

    float sumVal=0.0;

    for (i=0; i<d->dSize; i++)
        sumVal+=d->dataPtr[i]*(d->tIdx+1);

    printf("Thread %d calculated the value as %-11.11f\n",d->tIdx,sumVal);

    return(NULL);
}

В threadFun весь указатель d указывает на пространство общей памяти (я полагаю).Из того, с чем я столкнулся в документации чтение из нескольких потоков - это нормально.В CUDA чтения должны быть объединены - есть ли подобные ограничения выравнивания в pthreads?Т.е. если у меня есть два потока, читающие с одного и того же общего адреса, я предполагаю, что где-то вдоль линии планировщик должен поставить один поток впереди другого.В CUDA это может быть дорогостоящей операцией, и ее следует избегать.Существует ли штраф за «одновременное» чтение из общей памяти - и если да, то настолько ли он мал, что он незначителен?то есть обоим потокам может потребоваться одновременно прочитать d-> datPtr [0] - я предполагаю, что чтение из памяти не может происходить одновременно - это предположение неверно?* в котором говорится, что при многопоточности используется структура массивов - это согласуется с cuda.Однако, если я сделаю это, это почти неизбежно, мне понадобится идентификатор потока - который, я считаю, потребует от меня блокировки блокировки мьютекса идентификатором потока, пока он не будет считан в область потока, будет ли это так или будет другойопределить потоки?

Также приветствуется статья об управлении памятью для многопоточных программ.

Ответы [ 4 ]

2 голосов
/ 07 июня 2011

Пока указатель данных вашего потока d указывает на пространство общей памяти, если вы не увеличите этот указатель, чтобы попытаться выполнить чтение или запись в смежный элемент данных потока в массиве пространства общей памяти, вы в основном имеете дело слокализованные данные потока.Также значение args является локальным для каждого потока, поэтому в обоих случаях, если вы не увеличиваете сам указатель данных (т. Е. Никогда не вызываете что-то вроде d++ и т. Д., Чтобы указывать на другой поток).память потока), для защиты «принадлежности» к вашему потоку мьютекс не требуется.

Также и для идентификатора вашего потока, поскольку вы записываете только это значение из порождающего потока, а затем читаете это значениев реальном порожденном потоке нет необходимости в мьютексе или механизме синхронизации ... у вас есть только один производитель / потребитель для данных.Мьютексы и другие механизмы синхронизации необходимы, только если есть несколько потоков, которые будут считывать и записывать одно и то же местоположение данных.

1 голос
/ 08 июня 2011

ЦП имеют кеш. Чтения поступают из кеша, поэтому каждое ЦП / ядро ​​может читать из своего собственного кеша, пока соответствующая линия кеша SHARED. Записывает принудительные строки кэширования в состояние EXCLUSIVE, аннулируя соответствующие строки кэширования на других процессорах.

Если у вас есть массив с элементом в каждом потоке, и для этого массива есть и чтение, и запись, вы можете выровнять каждый элемент в кеш-линию, чтобы избежать ложного совместного использования.

0 голосов
/ 08 июня 2011

Исходя из CUDA, возможно, вы думаете, что сложно. POSIX-потоки намного проще. В основном то, что вы делаете, должно работать, пока вы читаете только в общем массиве.

Кроме того, не забывайте, что CUDA - это расчленение C ++, а не C, поэтому некоторые вещи могут отличаться от этого аспекта. Например, в вашем коде привычка приводить к возврату из malloc обычно не одобряется реальными программистами на Си, так как это может быть источником скрытых ошибок.

0 голосов
/ 07 июня 2011
  1. чтение памяти в одну и ту же область в другом потоке в одну и ту же память не является проблемой в системах с общей памятью (запись - другое дело, соответствующая область - строка кэша: в зависимости от 64-256 байтв системе)

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

...