Я пытаюсь вычислить максимальную пропускную способность, возможную для моего GPU для матричной матрицы *, умножения плотности, используя как можно больше вычислительных ресурсов.cuSparse Пропускная способность снижается при увеличении числа итераций
Для того, чтобы достичь этого я попробовал два метода:
Выделяет память для й и А на хосте. Храните x и A на хосте. Выделите память для x и A на устройстве. Храните x и A на устройстве. Таймер запуска. Выполняйте разреженную матрицу * плотное векторное умножение через cusparsecsrmv в цикле и запускайте cusparsecsrmv за NUM_ITERATIONS раз. Таймер остановки. Скопируйте y из устройства в хост и проверьте результат для точности.
Выделите память для x и A на хосте. Храните x и A на хосте. Выделите память для массива x и A на устройстве (т. Е. X [NUM_IMPS], A [NUM_IMPS]). Храните X и A на устройстве. Таймер запуска. Выполняйте разреженное умножение матрицы * с помощью cusparsecsrmv в цикле и запускайте cusparsecsrmv за NUM_IMPS раз на каждом A [i] * x [i]. Таймер остановки. Скопируйте y [NUM_IMPS-1] с устройства на хост и проверьте результат для точности.
Вот мой код для метода 1:
// == Start timer for just measuring multiplication ==
QueryPerformanceFrequency(&Frequency1);
QueryPerformanceCounter(&StartingTime1);
// Sparse matrix * dense vector multiplication
/* exercise Level 2 routines (csrmv) */
for (int i = 0; i < NUM_ITERATIONS; i++) {
status = cusparseScsrmv(handle, CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz,
&alpha, descr, cooVal, csrRowPtr, cooColIndex,
&xVal[0], &beta, &y[0]);
}
// == End time for just measuring multiplication ==
QueryPerformanceCounter(&EndingTime1);
ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart;
ElapsedMicroseconds1.QuadPart *= 1000000;
ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart;
Вот мой код для метода 2:
// == Start timer for just measuring multiplication ==
QueryPerformanceFrequency(&Frequency1);
QueryPerformanceCounter(&StartingTime1);
for (int i = 0; i < NUM_IMPS; i++) {
status = cusparseScsrmv(handle_array[i], CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz,
&alpha, descr_array[i], cooVal_array[i], csrRowPtr_array[i], cooColIndex_array[i],
&xVal_array[i][0], &beta, &y_array[i][0]);
}
// == End time for just measuring multiplication ==
QueryPerformanceCounter(&EndingTime1);
ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart;
ElapsedMicroseconds1.QuadPart *= 1000000;
ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart;
Если NUM_ITERATIONS или NUM_IMPS = 1, они получают такую же пропускную способность. Если NUM_IMPS = 10, максимальная пропускная способность. Однако, как только NUM_IMPS = 100 или более, пропускная способность начинает уменьшаться. Аналогично с NUM_ITERATIONS он начинает расти, но как только я поставил NUM_ITERATIONS на супер большом количестве, скажем, 100000 пропускная способность упадет ниже пропускной способности для NUM_ITERATIONS = 1.
Почему это происходит? Я бы ожидал, что thorughput просто насытится в какой-то момент и не сможет подняться выше, , но не уменьшится.
Мои мысли связаны с чем-то с несколькими вызовами cusparsecsrmv, которые GPU боятся, или, возможно, графическому процессору необходимо охладиться, поэтому он замедляется, поэтому пропускная способность снижается, но все это не кажется разумным выводы для меня.
Каков правильный способ измерения времени? Добавьте команду cudaDeviceSynchronize() сразу после всех вызовов? Я сделал это, и производительность танковала, намного ниже, чем я ожидал. – Veridian
Исполнение не было «танком». Вы только начали правильно его измерять. – talonmies
, так сколько итераций, по-вашему, я должен запустить до запуска cudaDeviceSynchronize? Кроме того, я просто запускаю cudaDeviceSynchronize без аргументов? – Veridian