2015-10-01 22 views
0

У меня возникло странное поведение, когда я запускаю 2 экземпляра ядра для одновременного запуска при совместном использовании ресурсов графического процессора.Одновременное выполнение двух процессов, совместно использующих Tesla K20

Я разработал ядро ​​CUDA, которое предназначено для работы в одном SM (многопроцессор), где потоки выполняют операцию несколько раз (с циклом).

Ядро готово создать только блок, поэтому использовать только один SM.

simple.cu

#include <cuda_runtime.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <helper_cuda.h> 
using namespace std; 

__global__ void increment(float *in, float *out) 
{ 
    int it=0, i = blockIdx.x * blockDim.x + threadIdx.x; 
    float a=0.8525852f; 

    for(it=0; it<99999999; it++) 
      out[i] += (in[i]+a)*a-(in[i]+a); 
} 

int main(int argc, char* argv[]) 
{ 
    int i; 
    int nBlocks = 1; 
    int threadsPerBlock = 1024; 
    float *A, *d_A, *d_B, *B; 
    size_t size=1024*13; 

    A = (float *) malloc(size * sizeof(float)); 
    B = (float *) malloc(size * sizeof(float)); 

    for(i=0;i<size;i++){ 
      A[i]=0.74; 
      B[i]=0.36; 
    } 

    cudaMalloc((void **) &d_A, size * sizeof(float)); 
    cudaMalloc((void **) &d_B, size * sizeof(float)); 

    cudaMemcpy(d_A, A, size, cudaMemcpyHostToDevice); 
    cudaMemcpy(d_B, B, size, cudaMemcpyHostToDevice); 

    increment<<<nBlocks,threadsPerBlock>>>(d_A, d_B); 

    cudaDeviceSynchronize(); 

    cudaMemcpy(B, d_B, size, cudaMemcpyDeviceToHost); 

    free(A); 
    free(B); 

    cudaFree(d_A); 
    cudaFree(d_B); 

    cudaDeviceReset(); 

    return (0); 
} 

Так что, если я исполню ядро:

time ./simple

я

real 0m36.659s user 0m4.033s sys 0m1.124s

В противном случае, если я выполнить два экземпляра:

time ./simple & time ./simple

я для каждого процесса:

real 1m12.417s user 0m29.494s sys 0m42.721s

real 1m12.440s user 0m36.387s sys 0m8.820s

Насколько мне известно, расстрелы должны работать одновременно длительностью один (около 36 секунд). Однако они продолжаются в два раза больше базового времени. Мы знаем, что GPU имеет 13 SM, каждый должен выполнить один блок, поэтому ядра создают только 1 блок.

Выполняются ли они в том же SM?

Не должны ли они работать одновременно в разных SM?

EDITED

Для того, чтобы сделать мне яснее я приложу профили одновременного выполнения, полученного от nvprof:

Profile, первый экземпляр simple.cu profile, first instance

профиля, второй экземпляр simple.cu profile, second instance

Теперь я хотел бы показать вам поведение одного и того же сценария, но одновременно выполнять два экземпляры matrixMul образца:

Profile, первый экземпляр enter image description here

профиля, второй экземпляр enter image description here

Как вы можете видеть, в первом сценарии, ядро ​​ждет другой, чтобы закончить. Хотя во втором сценарии (matrixMul) ядра из обоих контекстов запускаются одновременно.

спасибо.

ответ

3

Когда вы запускаете два отдельных процесса с использованием одного и того же графического процессора, каждый из них имеет свой собственный контекст. CUDA не поддерживает одновременное использование нескольких контекстов на одном устройстве. Вместо этого каждый контекст конкурирует за устройство неопределенным образом с переключением контекста уровня драйвера. Вот почему выполнение ведет себя так, как если бы процессы были сериализованы - фактически они есть, но на уровне драйвера, а не на графическом уровне.

Имеются технологии (MPS, Hyper-Q), которые могут делать то, что вы хотите, но способ, которым вы пытаетесь это сделать, не будет работать.


Редактировать, чтобы ответить на обновление в вашем вопросе:

Добавленный используя образец MatrixMul не показывает, что вы думаете, он делает пример. Это приложение запускает 300 коротких ядер и вычисляет показатель производительности в среднем за 300 запусков. Экран профилирования был настроен на очень грубое временное разрешение, так что он выглядит так, как будто у него есть один длинный запуск ядра, когда на самом деле это серия очень коротких ядер времени.

Чтобы проиллюстрировать это, рассмотрим следующее:

Это нормальное профилирование прогон для одного процесса MatrixMul работает на устройстве Kepler. Обратите внимание, что существует много отдельных ядер, работающих непосредственно друг за другом. enter image description here

Это профилирование следы двух одновременных процессов MatrixMul, работающих на одной и той же Kepler устройства: enter image description here enter image description here

Следует отметить, что существуют пробелы в профиле следов каждого процесса, это где переключение контекста между происходят два процесса. Поведение идентично вашему первоначальному примеру, только при гораздо более тонкой детализации. Как неоднократно повторялось несколько разных людей в ходе этого обсуждения - CUDA не поддерживает множественные контексты на образце устройства одновременно с использованием стандартного API времени выполнения. Сервер MPS делает, разрешив это добавлением демона, который перенаправляет API с помощью большого общего внутреннего конвейера Hyper-Q, но вы не используете его и не имеете никакого отношения к результатам, которые вы указали в этом вопросе.

+0

Я вижу, я не знал об этом, однако, когда я запускаю 2 параллельных экземпляра matrixMul из SDK, они запускаются одновременно. Я предполагаю, что увеличение времени выполнения связано с совместным использованием SM, но представленное ядро ​​настолько мало, что его можно запустить без совместного использования SM. Мы профилировали выполнение, и мы обнаружили, что наше ядро ​​блокирует выполнение другого ядра, в то время как ядро ​​matrixMul не блокирует другие исполнения. Ты знаешь почему? – siserte

+3

Matrixmul не будет запускать ядра одновременно либо из двух отдельных процессов. Вы что-то неправильно истолковываете. Приложения могут запускаться одновременно, но отдельные ядра не будут возникать из отдельных процессов. Профилировщик может проявлять какое-то перекрытие, но это будет представлять активность API. Сами ядра не будут запускаться одновременно. –

+0

Благодарим за ответ, но мы запускаем 2 экземпляра matrixMul, где выполняются 2 ядра в каждом из них. Профили обоих исполнений показывают, что в то же время одновременно работают 2 ядра. Насколько я знаю, CUDA может одновременно обрабатывать несколько ядер. – siserte