LINUX.ORG.RU

Не работает ассемблерная вставка

 , , ,


0

3

Пишу на go однин модуль, задачу которую будет решать модуль - ресурсоёмка, предположительно на решение задачи будет уходить несколько часов, а то и дней, поэтому крайне важно сделать модуль максимально производительным. Сама задача неплохо векторизируется и распаралеливается, для векторизации использую функции на си с ассемблерными вставками. Ни разу не использовал связку c+asm, нагуглил как пользоваться и написал функцию на си, но ассемблерная вставка в функции не работает, вначале думал, что в вставке ошибка, решил посмотреть как вставка изменяют переменную с которой работает и просто вывел её через printf, после этого всё начало работать как положено, убираю printf и всё опять перестаёт работать. С printf работает даже если он не выводит никакой переменной. Прошу помощи с решением этой задачи, вот код:

#include <stdint.h>
__attribute__((always_inline)) inline uint32_t foo(int size, void *data1, void *data2){
	uint32_t tmpSum[4] __attribute__ ((aligned (16))) = {0, 0, 0, 0};
	uint32_t sum = 0;
	uint64_t offset = 0;
 	for (; size - offset >= 16; offset += 16){
		asm (	"movups (%0), %%xmm1\n"
			"pmulhuw (%1), %%xmm1\n"
			"movdqa %%xmm1, %%xmm2\n"
			"pxor %%xmm3, %%xmm3\n"
			"punpcklwd %%xmm3, %%xmm1\n"
			"punpckhwd %%xmm3, %%xmm2\n"
			"paddd %%xmm2, %%xmm1\n"
			"paddd (%2), %%xmm1\n"
			"movdqa %%xmm1, (%2)" : : "r" (data1 + offset), "r" (data2 + offset), "r" (tmpSum)
 		);
		//printf вставлял сюда
 	};
	for (;offset != size; offset += 2){
		sum += (uint32_t)(*(uint16_t *)(data1+offset)) * (uint32_t)(*(uint16_t *)(data2+offset));
 	};
	sum = sum >> 16;
	sum += tmpSum[0] + tmpSum[1] + tmpSum[2] + tmpSum[3];
	return sum;
}

gcc считает, что нет выходных данных

сохранение результата в tmpSum не обозначено для gcc

там же сказано

asm(code : output : input)

а у тебя output нет.

В доке был отдельно описан вариант когда результат записывается в один из входных параметров.

На крайняк tmpSum укажи volatile

Нафига тебе tmpSum? Загони цикл в asm и накапливай результат в одном из %xmm

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 1)

там еще как-то нужно было объяснять gcc, что ты используешь доп. регистры xmm1-xmm3

vel ★★★★★ ()

а что вставка вообще делает, какой алгоритм реализует, сначала это распиши

Harald ★★★★★ ()
Ответ на: комментарий от vel

asm(code : output : input)

а у тебя output нет.

Спасибо за помощь, при указании tmpSum как output заработало.

Нафига тебе tmpSum? Загони цикл в asm и накапливай результат в одном из %xmm

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

Taetricus ()
Ответ на: комментарий от Taetricus

Тут либо медленно и просто, либо быстро и сложно.

Посмотри на результирующий ассемблерный код - будет понятно на сколько эффективно оптимизатор gcc переварил эту вставку.

vel ★★★★★ ()

Вроде функция не такая сложная, не лучше будет написать всю функцию на go assembly, не дергая си?

MLP_Fan ★★ ()
Ответ на: комментарий от vel

Посмотри на результирующий ассемблерный код - будет понятно на сколько эффективно оптимизатор gcc переварил эту вставку.

Здесь сишный код предельно простой, сомневатюсь что gcc не справиться с адекватной оптимизацией этого кода.

Taetricus ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.