Сколько памяти вы можете передать и из функции ядра в cuda c? - PullRequest
0 голосов
/ 25 октября 2018

Я делаю программу, которая читает из входных данных два числа, N и K, затем читает N целых чисел и сохраняет их в массив.Цель программы состоит в том, чтобы вычислить максимальное среднее значение всех сегментов длиной не менее K. Затем она печатает это среднее значение (умноженное на 1000 и усекающее десятичные знаки).

Это задача в соревновании по программированию. Iучаствовал один раз, и существует решение O (n log (n)) для этой проблемы.Тем не менее, я думаю, что использование графической карты вместо процессора должно быть достаточно для решения O (n ^ 2) с использованием памяти O (n).По какой-то причине, хотя, когда я достигаю входов около 90 000, программа завершает работу с исключением шины.

#include <bits/stdc++.h>
using namespace std;

__global__
void solve(int n, int k, int *a, int *x) {
    // i is the beginning of the segment
    for (int i = threadIdx.x; i < n; i += blockDim.x) {
        int sum = 0;
        // j is the end of the segment
        for (int j = i; j < n; j++) {
            sum = sum + a[j];
            if (j-i+1 >= k && x[threadIdx.x] < sum * 1000ll / (j-i+1))
                x[threadIdx.x] = sum * 1000ll / (j-i+1);
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    // n = number of elements, k = minimum segment length, T = number    of threads
    int n, k, T = 256;
    cin >> n >> k;

    // a = input array, x = array of results (one for each thread, so no two threads write to the same place at the same time)
    int *a, *x;

    // https://devblogs.nvidia.com/even-easier-introduction-cuda/ here I just copy their approach
    cudaMallocManaged(&a, n*sizeof(int));
    cudaMallocManaged(&x, T*sizeof(int));

    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < T; i++)
        x[i] = 0;

    solve<<<1, T>>>(n, k, a, x);

    cudaDeviceSynchronize();

    // the result is the maximum of all results
    int res = 0;
    for (int i = 0; i < T; i++)
        res = max(res, x[i]);
    cout << res << endl;

    cudaFree(a);
    cudaFree(x);

    return 0;
}

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

    for (int i = 0; i < T; i++)
        res = max(res, x[i]);

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

Программа отлично работает для входных массивов длиной <= 30 000. Это может означать, что я выделяю слишком много памяти, однако могупросто запустите эту программу с элементами 1e7 (скопировано из еще более простого введения).</p>

#include <iostream>
#include <math.h>
// Kernel function to add the elements of two arrays
__global__
void add(int n, float *x, float *y)
{
  for (int i = 0; i < n; i++)
    y[i] = x[i] + y[i];
}

int main(void)
{
  int N = 1<<20;
  float *x, *y;

  // Allocate Unified Memory – accessible from CPU or GPU
  cudaMallocManaged(&x, N*sizeof(float));
  cudaMallocManaged(&y, N*sizeof(float));

  // initialize x and y arrays on the host
  for (int i = 0; i < N; i++) {
    x[i] = 1.0f;
    y[i] = 2.0f;
  }

  // Run kernel on 1M elements on the GPU
  add<<<1, 1>>>(N, x, y);

  // Wait for GPU to finish before accessing on host
  cudaDeviceSynchronize();

  // Check for errors (all values should be 3.0f)
  float maxError = 0.0f;
  for (int i = 0; i < N; i++)
    maxError = fmax(maxError, fabs(y[i]-3.0f));
  std::cout << "Max error: " << maxError << std::endl;

  // Free memory
  cudaFree(x);
  cudaFree(y);

  return 0;
}

Моя видеокарта 750M.

...