Задача очень проста, выписывая последовательность целых переменных в память:
Исходный код:
for (size_t i=0; i<1000*1000*1000; ++i)
{
data[i]=i;
};
Параллельный код:
size_t stepsize=len/N;
#pragma omp parallel num_threads(N)
{
int threadIdx=omp_get_thread_num();
size_t istart=stepsize*threadIdx;
size_t iend=threadIdx==N-1?len:istart+stepsize;
#pragma simd
for (size_t i=istart; i<iend; ++i)
x[i]=i;
};
Производительность отстойная, требуется 1,6 сек для записи переменных 1G uint64
(что равно 5 ГБ в секунду), путем простого распараллеливания (open mp parallel
) вышеуказанного кода, скорости увеличение abit, но производительность все еще отстойная, возьмите 1,4 с с 4 потоками и 1,35 с 6 потоками на i7 3970.
Пространственная пропускная способность памяти моей платформы (i7 3970/64G DDR3-1600) 51,2 ГБ/с, для приведенного выше примера достигнутая пропускная способность памяти около 1/10 теоретической полосы пропускания, даже через приложение в значительной степени ограничено пропускной способностью.
Кто-нибудь знает, как улучшить код?
Я написал много кода с привязкой к памяти на GPU, довольно просто для GPU, чтобы в полной мере использовать пропускную способность памяти устройства GPU (например, 85% + теоретической полосы пропускания).
EDIT:
Код компилируется Intel ICC 13.1, до 64-битного двоичного кода и с максимальным оптимизацией (O3) и AVX-кодом, а также с автоматической автолизацией.
UPDATE:
Я пробовал все коды ниже (спасибо Paul R), ничего особенного не происходит, я считаю, что компилятор полностью способен выполнять оптимизацию simd/vectorization.
Что касается того, почему я хочу заполнить цифры там, ну, длинный рассказ короткий:
Его часть высокопроизводительного гетерогенного вычисления algorthim со стороны устройства algorthim очень эффективна до такой степени, что набор с несколькими GPU настолько быстр, что я обнаружил, что узкое место производительности случается, когда CPU пытается напишите несколько секунд в памяти.
Из-за этого, зная, что процессор сосет при заполнении номеров (в отличие от этого, графический процессор может заполнять последовательность номеров с очень близкой скоростью ( 238 ГБ/с из 288 ГБ/с на GK110 против жалкого 5 ГБ/сек из 51,2 ГБ/сек на CPU) до теоретической пропускной способности глобальной памяти GPU), я мог бы немного изменить свой algorthim, но то, что заставляет меня задаться вопросом, почему CPU так плохо всасывает при заполнении количества номеров здесь.
Что касается пропускной способности памяти моей установки, я считаю, что ширина полосы пропускания (51,2 ГБ) примерно соответствует правилу на основе теста memcpy()
, достигнутая ширина полосы пропускания составляет около 80% + теоретической полосы пропускания (> 40GB/сек).