Не могу отладить код с двумя потоками

Написал следующий код (привожу не весь):

  1. int N=4*1024;
  2. for (int i=0; i<N; i+=2*1024){
  3.  
  4.                 cudaMemcpyToSymbolAsync(dev_a0, a+i, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream0);
  5.                 cudaMemcpyToSymbolAsync(dev_a1, a+i+1024, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream1);
  6.  
  7.                 cudaMemcpyToSymbolAsync(dev_b0, b+i, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream0);
  8.                 cudaMemcpyToSymbolAsync(dev_b1, b+i+1024, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream1);
  9.  
  10.                 dot<<<blocksPerGrid, treadsPerBlock, 0, stream0>>> (dev_a0, dev_b0, dev_c0);
  11.                 dot<<<blocksPerGrid, treadsPerBlock, 0, stream1>>> (dev_a1, dev_b1, dev_c1);
  12.  
  13.                 cudaMemcpyAsync(partial_c + i/32, dev_c0, blocksPerGrid*sizeof(float), cudaMemcpyDeviceToHost, stream0);
  14.                 cudaMemcpyAsync(partial_c + (i+1024)/32, dev_c1, blocksPerGrid*sizeof(float), cudaMemcpyDeviceToHost, stream1);
  15.         }

Смысл кода: двумя потоками в константную память (так как она ограничена) кладутся части векторов (dev_a0, dev_b0), у которых находится скалярное произведение. Результат вычисления ядра (dev_c0) перебрасывается в общий массив (позже сумма этих "кусочков" будет подсчитана CPU). Так вот на второй итерации на последней строке в цикле происходит ошибка.

В отладчике дается предупреждение о необходимости установить ключи регистра в HKEY_LOCAL_MACHINE\_SYSTEM\CurrentControlSet\Control\GraphicsDrivers (прямо на уровне этой папки): TdrDelay( добавил и поставил значение 90) и TdrLevel(добавил и поставил 0).

Все равно все виснет (причем тесты computing SDK отлично работают и не про какую остановку драйвера монитора не сообщают). В правом нижнем углу также нет всплывающего сообщения от Windows 7 (Professional X64) (раньше было, так что как это выглядит я знаю). Код пишу в Visual studio 2010 (использую шаблон CUDA 4.0 RunTime). Видеокарточка: ASUS GTX 560ti TOP (ядро работает на 900МГц)

Один поток отлично работал, но решил немного поэксперементировать... Почему стопарится выполнение?

Forums: 

Код почему-то

Код почему-то обрезался...:

  1. int N=4*1024;
  2. for (int i=0; i<N; i+=2*1024){
  3.  
  4.                 cudaMemcpyToSymbolAsync(dev_a0, a+i, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream0);
  5.                 cudaMemcpyToSymbolAsync(dev_a1, a+i+1024, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream1);
  6.  
  7.                 cudaMemcpyToSymbolAsync(dev_b0, b+i, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream0);
  8.                 cudaMemcpyToSymbolAsync(dev_b1, b+i+1024, 1024*sizeof(float), 0, cudaMemcpyHostToDevice, stream1);
  9.  
  10.                 dot<<<blocksPerGrid, treadsPerBlock, 0, stream0>>> (dev_a0, dev_b0, dev_c0);
  11.                 dot<<<blocksPerGrid, treadsPerBlock, 0, stream1>>> (dev_a1, dev_b1, dev_c1);
  12.  
  13.                 cudaMemcpyAsync(partial_c + i/32, dev_c0, blocksPerGrid*sizeof(float), cudaMemcpyDeviceToHost, stream0);
  14.                 cudaMemcpyAsync(partial_c + (i+1024)/32, dev_c1, blocksPerGrid*sizeof(float), cudaMemcpyDeviceToHost, stream1);
  15.         }

Знаете, я не знаю в чем тут

Знаете, я не знаю в чем тут конкретно ваша ошибка (вероятно, в коде kernel, который вы не приводите, но виснет то именно он), но

1) Копировать на одну карту по кусочкам особого смысла нет. Был бы смысл, если бы вы перекрывали копирование и исполнение, но вы то этого не делаете.

2) выгружать на видеокарту скалярное произведение двух векторов тоже смысла нет. Для этой задачи вы будете ограничены скоростью PCI-express (4-5-6Gb/sec), а на CPU сможете делать ту же задачу со скоростью памяти (20+Gb/sec на современных CPU)

1. Висит не ядро, а последняя

1. Висит не ядро, а последняя передача массива с девайса на хост.
2. Копирование и исполнение перекрываются (этот прием хорошо описан в книге "Технология CUDA в примерах"): так как очередь каждого потока выполняется последовательно то необходимо именно в такой последовательности ставить задачи в очередь.
3. Это эксперементальная программа, поэтому я просто учусь делать все возможные операции.

Ошибку нашел: она крылась в использовании константной памяти (хотя почему предложенный вариант не работает- не знаю). Замена на копирование в обычную память устройства решила вопрос.